Prepare data

Read and format data

Prevalence

df_uk_prev <- read_csv('UK_timeseries_prep_2005.csv')
Parsed with column specification:
cols(
  ut_area = col_character(),
  date = col_character(),
  cumcase = col_double(),
  poptotal = col_double(),
  rate = col_double()
)
df_uk_prev <- df_uk_prev %>% 
  select(ut_area, date, rate) %>% 
  rename(rate_day = rate) %>%
  mutate(date = as.Date(date, "%d%b%Y"))

df_uk_prev

Personality


df_uk_pers <- read_csv('timeseries_uk_utla_march9_april_09.csv')
Parsed with column specification:
cols(
  ut_area = col_character(),
  time = col_double(),
  areaname = col_character(),
  open = col_double(),
  extra = col_double(),
  agree = col_double(),
  neuro = col_double(),
  sci = col_double(),
  frequ = col_double(),
  ut_name = col_character(),
  poptotal = col_double(),
  rate_day = col_double()
)
df_uk_pers <- df_uk_pers %>% 
  select(ut_area, open, agree, neuro, sci, extra) %>% 
  dplyr::rename(pers_o = open, 
         pers_c = sci,
         pers_e = extra,
         pers_a = agree,
         pers_n = neuro) %>%
  distinct()

df_uk_pers
NA

Social distancing

df_uk_socdist <- read_csv('UK_socdist_fb_nuts3.csv')
Parsed with column specification:
cols(
  nuts3 = col_character(),
  date = col_date(format = ""),
  all_day_bing_tiles_visited_relat = col_double(),
  all_day_ratio_single_tile_users = col_double(),
  open = col_double(),
  extra = col_double(),
  agree = col_double(),
  neuro = col_double(),
  sci = col_double(),
  frequ = col_double(),
  nuts3_name = col_character(),
  runday = col_double()
)
df_uk_socdist$date %>% summary()
        Min.      1st Qu.       Median         Mean      3rd Qu.         Max. 
"2020-03-01" "2020-03-08" "2020-03-16" "2020-03-16" "2020-03-24" "2020-03-31" 
df_uk_socdist <- df_uk_socdist %>% select(-runday, -frequ) %>%
  dplyr::rename(pers_o = open, 
                pers_c = sci,
                pers_e = extra,
                pers_a = agree,
                pers_n = neuro) %>% 
  select(-nuts3_name) %>% 
  dplyr::rename(socdist_tiles = all_day_bing_tiles_visited_relat,
                socdist_single_tile = all_day_ratio_single_tile_users) %>%
  drop_na()

df_uk_socdist

Controls

df_uk_ctrl_nuts <- read_csv("controls_UK_nuts3.csv")
Parsed with column specification:
cols(
  nuts3 = col_character(),
  nuts3_name = col_character(),
  airport_dist = col_double(),
  males = col_double(),
  popdens = col_double(),
  manufacturing = col_double(),
  tourism = col_double(),
  health = col_double(),
  academic = col_double(),
  medinc = col_double(),
  medage = col_double(),
  conservative = col_double()
)
df_uk_ctrl_nuts <- df_uk_ctrl_nuts %>% select(-nuts3_name)
df_uk_ctrl_nuts


df_uk_ctrl_ut <- read_csv("controls_UK_ut.csv")
Parsed with column specification:
cols(
  ut_area = col_character(),
  ut_name = col_character(),
  airport_dist = col_double(),
  males = col_double(),
  popdens = col_double(),
  manufacturing = col_double(),
  tourism = col_double(),
  health = col_double(),
  academic = col_double(),
  medinc = col_double(),
  medage = col_double(),
  conservative = col_double()
)
df_uk_ctrl_ut <- df_uk_ctrl_ut %>% select(-ut_name)
df_uk_ctrl_ut
NA
NA

Merge prevalence data

df_uk <- df_uk_prev %>% 
  plyr::join(df_uk_pers, by='ut_area') %>% 
  plyr::join(df_uk_ctrl_ut, by='ut_area')

# create sequence of dates
date_sequence <- seq.Date(min(df_uk$date),
                          max(df_uk$date), 1)
                     
# create data frame with time sequence
df_dates = tibble(date_sequence, 1:length(date_sequence)) 
names(df_dates) <- c('date', 'time')

# merge day index with gps data
df_uk = df_uk %>% 
  merge(df_dates, by='date') %>% 
  arrange(ut_area) %>%
  as_tibble()

df_uk

Merge social distancing data

Identify London areas


nuts_london_inner <- c('UKI31','UKI32','UKI33','UKI34','UKI41',
                      'UKI42','UKI43','UKI44','UKI45')

nuts_london_outer <- c('UKI51','UKI52','UKI53','UKI54','UKI61',
                      'UKI62','UKI63','UKI71','UKI72','UKI73',
                      'UKI74','UKI75')

ut_london_inner <- c('E09000007','E09000001','E09000033','E09000013',
                    'E09000020','E09000032','E09000025','E09000012',
                    'E09000030','E09000014','E09000019','E09000023',
                    'E09000028','E09000022')

ut_london_outer <- c('E09000011','E09000004','E09000016','E09000002',
                    'E09000031','E09000026','E09000010','E09000006',
                    'E09000008','E09000029','E09000021','E09000024',
                    'E09000003','E09000005','E09000009','E09000017',
                    'E09000015','E09000018','E09000027')

df_uk = df_uk %>% 
  mutate(london = ifelse(ut_area %in% ut_london_inner, 'london_inner', 
                       ifelse(ut_area %in% ut_london_outer, 'london_outer',
                              'country'))) %>%
  mutate(london = as.factor(london))

df_uk_socdist = df_uk_socdist %>% 
  mutate(london = ifelse(nuts3 %in% nuts_london_inner, 'london_inner', 
                       ifelse(nuts3 %in% nuts_london_outer, 'london_outer',
                              'country'))) %>%
  mutate(london = as.factor(london))

Explore data

Plot prevalence over time


df_uk %>% ggplot(aes(x=time, y=rate_day)) + 
  geom_point(aes(col=ut_area, size=popdens)) + 
  geom_smooth(method="loess", se=T) + 
  theme(legend.position="none") +
  ggtitle("Overall prevalence over time")


pers <- c('pers_o', 'pers_c', 'pers_e', 'pers_a', 'pers_n')

for (i in pers){

gg <- df_uk %>% mutate(prev_tail = cut(.[[i]], 
                                       breaks = c(-Inf, quantile(.[[i]], 0.2), quantile(.[[i]], 0.8), Inf),
                                       labels = c('lower tail', 'center', 'upper tail'))) %>% 
  filter(prev_tail != 'center') %>%
  ggplot(aes(x=time, y=rate_day)) + 
  geom_point(aes(col=ut_area, size=popdens)) + 
  geom_smooth(method="loess", se=T) + 
  facet_wrap(~prev_tail) + 
  theme(legend.position="none") +
  ggtitle(i)

print(gg)
}

Plot social distancing over time


df_uk_socdist %>% ggplot(aes(x=time, y=socdist_single_tile)) + 
  geom_point(aes(col=nuts3, size=popdens)) + 
  geom_smooth(method="loess", se=T) + 
  theme(legend.position="none") +
  ggtitle("Overall social distancing over time")


pers <- c('pers_o', 'pers_c', 'pers_e', 'pers_a', 'pers_n')

for (i in pers){

gg <- df_uk_socdist %>% mutate(socdist_tail = cut(.[[i]], 
                                       breaks = c(-Inf, quantile(.[[i]], 0.2), quantile(.[[i]], 0.8), Inf),
                                       labels = c('lower tail', 'center', 'upper tail'))) %>% 
  filter(socdist_tail != 'center') %>%
  ggplot(aes(x=time, y=socdist_single_tile)) + 
  geom_point(aes(col=nuts3, size=popdens)) + 
  geom_smooth(method="loess", se=T) + 
  facet_wrap(~socdist_tail) + 
  theme(legend.position="none") +
  ggtitle(i)

print(gg)
}

Explore differences between london and the rest


df_uk %>% ggplot(aes(x=time, y=rate_day)) + 
  geom_point(aes(col=ut_area, size=popdens)) + 
  geom_smooth(method="loess", se=T) + 
  theme(legend.position="none") +
  facet_wrap(~london) +
  ggtitle("Overall prevalence over time")

NA
NA
NA
df_uk_socdist %>% ggplot(aes(x=time, y=socdist_single_tile)) + 
  geom_point(aes(col=nuts3, size=popdens)) + 
  geom_smooth(method="loess", se=T) + 
  theme(legend.position="none") +
  facet_wrap(~london) +
  ggtitle("Overall social distancing over time")

Control for weekend effect


df_uk_socdist %>% ggplot(aes(x=time, y=socdist_single_tile_clean)) + 
  geom_point(aes(col=nuts3, size=popdens)) + 
  geom_smooth(method="loess", se=T) + 
  theme(legend.position="none") +
  ggtitle("Overall social distancing over time")


pers <- c('pers_o', 'pers_c', 'pers_e', 'pers_a', 'pers_n')

for (i in pers){

gg <- df_uk_socdist %>% mutate(socdist_tail = cut(.[[i]], 
                                       breaks = c(-Inf, quantile(.[[i]], 0.2), quantile(.[[i]], 0.8), Inf),
                                       labels = c('lower tail', 'center', 'upper tail'))) %>% 
  filter(socdist_tail != 'center') %>%
  ggplot(aes(x=time, y=socdist_single_tile_clean)) + 
  geom_point(aes(col=nuts3, size=popdens)) + 
  geom_smooth(method="loess", se=T) + 
  facet_wrap(~socdist_tail) + 
  theme(legend.position="none") +
  ggtitle(i)

print(gg)
}


df_uk_socdist <- df_uk_socdist %>% mutate(socdist_single_tile = socdist_single_tile_clean) %>% 
  select(-loess, -socdist_single_tile_clean)

Correlations


df_uk %>% group_by(ut_area) %>% 
  summarize_if(is.numeric, mean, na.rm=T) %>% 
  select(-ut_area, -time) %>% 
  cor(use = 'pairwise.complete') %>% round(3)
              rate_day pers_o pers_a pers_n pers_c pers_e airport_dist  males popdens manufacturing tourism health
rate_day         1.000  0.249 -0.256  0.080 -0.425  0.199       -0.452  0.035   0.420        -0.197  -0.280  0.133
pers_o           0.249  1.000 -0.604 -0.143 -0.636  0.734       -0.247  0.437   0.806        -0.532   0.116  0.089
pers_a          -0.256 -0.604  1.000 -0.197  0.643 -0.412        0.285 -0.460  -0.745         0.496   0.069 -0.001
pers_n           0.080 -0.143 -0.197  1.000 -0.353 -0.497        0.059  0.096   0.043         0.359  -0.244  0.138
pers_c          -0.425 -0.636  0.643 -0.353  1.000 -0.293        0.327 -0.524  -0.727         0.363   0.227 -0.286
pers_e           0.199  0.734 -0.412 -0.497 -0.293  1.000       -0.262  0.197   0.617        -0.595   0.098  0.026
airport_dist    -0.452 -0.247  0.285  0.059  0.327 -0.262        1.000 -0.124  -0.381         0.300   0.448  0.150
males            0.035  0.437 -0.460  0.096 -0.524  0.197       -0.124  1.000   0.510        -0.259  -0.094 -0.012
popdens          0.420  0.806 -0.745  0.043 -0.727  0.617       -0.381  0.510   1.000        -0.545  -0.099  0.112
manufacturing   -0.197 -0.532  0.496  0.359  0.363 -0.595        0.300 -0.259  -0.545         1.000  -0.088 -0.023
tourism         -0.280  0.116  0.069 -0.244  0.227  0.098        0.448 -0.094  -0.099        -0.088   1.000  0.049
health           0.133  0.089 -0.001  0.138 -0.286  0.026        0.150 -0.012   0.112        -0.023   0.049  1.000
academic         0.219  0.707 -0.502 -0.447 -0.298  0.730       -0.369  0.267   0.602        -0.714   0.056 -0.228
medinc           0.235  0.533 -0.533 -0.335 -0.300  0.569       -0.379  0.367   0.631        -0.532  -0.062 -0.243
medage          -0.345 -0.508  0.582 -0.167  0.780 -0.337        0.447 -0.620  -0.705         0.472   0.435 -0.153
conservative    -0.260 -0.843  0.511  0.366  0.485 -0.767        0.396 -0.293  -0.686         0.657  -0.023  0.043
              academic medinc medage conservative
rate_day         0.219  0.235 -0.345       -0.260
pers_o           0.707  0.533 -0.508       -0.843
pers_a          -0.502 -0.533  0.582        0.511
pers_n          -0.447 -0.335 -0.167        0.366
pers_c          -0.298 -0.300  0.780        0.485
pers_e           0.730  0.569 -0.337       -0.767
airport_dist    -0.369 -0.379  0.447        0.396
males            0.267  0.367 -0.620       -0.293
popdens          0.602  0.631 -0.705       -0.686
manufacturing   -0.714 -0.532  0.472        0.657
tourism          0.056 -0.062  0.435       -0.023
health          -0.228 -0.243 -0.153        0.043
academic         1.000  0.733 -0.382       -0.888
medinc           0.733  1.000 -0.481       -0.661
medage          -0.382 -0.481  1.000        0.486
conservative    -0.888 -0.661  0.486        1.000
df_uk_socdist %>% group_by(nuts3) %>% 
  summarize_if(is.numeric, mean, na.rm=T) %>% 
  select(-nuts3, -time) %>% 
  cor(use = 'pairwise.complete') %>% round(3)
                    socdist_tiles socdist_single_tile pers_o pers_e pers_a pers_n pers_c airport_dist  males popdens
socdist_tiles               1.000              -0.467 -0.632 -0.735  0.546  0.337  0.397        0.530 -0.296  -0.711
socdist_single_tile        -0.467               1.000  0.189  0.235 -0.276  0.091 -0.211       -0.270 -0.004   0.376
pers_o                     -0.632               0.189  1.000  0.717 -0.604 -0.128 -0.655       -0.231  0.522   0.805
pers_e                     -0.735               0.235  0.717  1.000 -0.460 -0.451 -0.374       -0.319  0.246   0.644
pers_a                      0.546              -0.276 -0.604 -0.460  1.000 -0.203  0.659        0.328 -0.568  -0.748
pers_n                      0.337               0.091 -0.128 -0.451 -0.203  1.000 -0.324        0.072  0.190   0.020
pers_c                      0.397              -0.211 -0.655 -0.374  0.659 -0.324  1.000        0.326 -0.630  -0.737
airport_dist                0.530              -0.270 -0.231 -0.319  0.328  0.072  0.326        1.000 -0.155  -0.377
males                      -0.296              -0.004  0.522  0.246 -0.568  0.190 -0.630       -0.155  1.000   0.613
popdens                    -0.711               0.376  0.805  0.644 -0.748  0.020 -0.737       -0.377  0.613   1.000
manufacturing               0.676              -0.349 -0.497 -0.607  0.430  0.351  0.310        0.272 -0.179  -0.492
tourism                     0.225              -0.055  0.083 -0.011  0.129 -0.137  0.194        0.492 -0.168  -0.130
health                      0.132              -0.034  0.087  0.045  0.004  0.155 -0.275        0.180  0.023   0.166
academic                   -0.802               0.198  0.713  0.742 -0.491 -0.432 -0.324       -0.379  0.263   0.574
medinc                     -0.767               0.320  0.552  0.582 -0.620 -0.247 -0.367       -0.389  0.440   0.652
medage                      0.569              -0.218 -0.512 -0.402  0.631 -0.181  0.790        0.469 -0.672  -0.714
conservative                0.751              -0.172 -0.837 -0.761  0.514  0.338  0.522        0.389 -0.350  -0.678
rate_day                   -0.705               0.361  0.591  0.563 -0.549 -0.125 -0.457       -0.397  0.267   0.695
                    manufacturing tourism health academic medinc medage conservative rate_day
socdist_tiles               0.676   0.225  0.132   -0.802 -0.767  0.569        0.751   -0.705
socdist_single_tile        -0.349  -0.055 -0.034    0.198  0.320 -0.218       -0.172    0.361
pers_o                     -0.497   0.083  0.087    0.713  0.552 -0.512       -0.837    0.591
pers_e                     -0.607  -0.011  0.045    0.742  0.582 -0.402       -0.761    0.563
pers_a                      0.430   0.129  0.004   -0.491 -0.620  0.631        0.514   -0.549
pers_n                      0.351  -0.137  0.155   -0.432 -0.247 -0.181        0.338   -0.125
pers_c                      0.310   0.194 -0.275   -0.324 -0.367  0.790        0.522   -0.457
airport_dist                0.272   0.492  0.180   -0.379 -0.389  0.469        0.389   -0.397
males                      -0.179  -0.168  0.023    0.263  0.440 -0.672       -0.350    0.267
popdens                    -0.492  -0.130  0.166    0.574  0.652 -0.714       -0.678    0.695
manufacturing               1.000  -0.052 -0.067   -0.640 -0.462  0.413        0.627   -0.403
tourism                    -0.052   1.000  0.024    0.005 -0.138  0.485        0.012   -0.087
health                     -0.067   0.024  1.000   -0.202 -0.261 -0.154        0.010   -0.012
academic                   -0.640   0.005 -0.202    1.000  0.724 -0.368       -0.891    0.624
medinc                     -0.462  -0.138 -0.261    0.724  1.000 -0.479       -0.653    0.595
medage                      0.413   0.485 -0.154   -0.368 -0.479  1.000        0.499   -0.475
conservative                0.627   0.012  0.010   -0.891 -0.653  0.499        1.000   -0.610
rate_day                   -0.403  -0.087 -0.012    0.624  0.595 -0.475       -0.610    1.000

Modelling

Prepare functions


# function calculates all relevant models
run_models <- function(y, lvl1_x, lvl2_x, lvl2_id, data, ctrls=F){

  # subset data
  data = data %>% 
    dplyr::select(all_of(y), all_of(lvl1_x), all_of(lvl2_x), all_of(lvl2_id), 
                  popdens, rate_day, all_of(y))
  data = data %>% 
    dplyr::rename(y = all_of(y),
           lvl1_x = all_of(lvl1_x),
           lvl2_x = all_of(lvl2_x),
           lvl2_id = all_of(lvl2_id)
           )
  
  # configure optimization procedure
  ctrl_config <- lmeControl(opt = 'optim', maxIter = 100, msMaxIter = 100)

  # baseline
  baseline <- lme(fixed = y ~ 1, random = ~ 1 | lvl2_id, 
                    data = data,
                    correlation = corAR1(),
                  control = ctrl_config,
                  method = 'ML')

  # random intercept fixed slope
  random_intercept <- lme(fixed = y ~ lvl1_x + lvl2_x, 
                          random = ~ 1 | lvl2_id,
                            data = data,
                            correlation = corAR1(),
                  control = ctrl_config,
                  method = 'ML')

  # random intercept random slope
  random_slope <- lme(fixed = y ~ lvl1_x + lvl2_x, 
                      random = ~ lvl1_x | lvl2_id, 
                        data = data,
                        correlation = corAR1(),
                  control = ctrl_config,
                  method = 'ML')

  # cross level interaction
  interaction <- lme(fixed = y ~ lvl1_x * lvl2_x, 
                     random = ~ lvl1_x | lvl2_id, 
                       data = data,
                       correlation = corAR1(),
                  control = ctrl_config,
                  method = 'ML')
  
  # create list with results
  results <- list('baseline' = baseline, 
                  "random_intercept" = random_intercept, 
                  "random_slope" = random_slope,
                  "interaction" = interaction)
  
  
  if (ctrls == 'dem' | ctrls == 'prev'){
    
    # random intercept random slope
    random_slope_ctrl_dem <- lme(fixed = y ~ lvl1_x + lvl2_x + popdens,
                              random = ~ lvl1_x | lvl2_id, 
                          data = data,
                          correlation = corAR1(),
                    control = ctrl_config,
                  method = 'ML')
  
    # cross level interaction
    interaction_ctrl_main_dem <- lme(fixed = y ~ lvl1_x * lvl2_x + popdens,
                             random = ~ lvl1_x | lvl2_id, 
                         data = data,
                         correlation = corAR1(),
                    control = ctrl_config,
                  method = 'ML')
  
    # cross level interaction
    interaction_ctrl_int_dem <- lme(fixed = y ~ lvl1_x * lvl2_x + lvl1_x * popdens,
                             random = ~ lvl1_x | lvl2_id, 
                         data = data,
                         correlation = corAR1(),
                    control = ctrl_config,
                  method = 'ML')        
    
    # create list with results
    results <- list('baseline' = baseline, 
                    "random_intercept" = random_intercept, 
                    "random_slope" = random_slope,
                    "interaction" = interaction,
                    "random_slope_ctrl_dem" = random_slope_ctrl_dem,
                    "interaction_ctrl_main_dem" = interaction_ctrl_main_dem,
                    "interaction_ctrl_int_dem" = interaction_ctrl_int_dem)
  }
  
  if (ctrls == 'prev'){
  
    # random intercept random slope
    random_slope_ctrl_prev <- lme(fixed = y ~ lvl1_x + lvl2_x + popdens + rate_day,
                              random = ~ lvl1_x + rate_day | lvl2_id, 
                          data = data,
                          correlation = corAR1(),
                          control = ctrl_config,
                  method = 'ML')  
    
        # cross level interaction
    interaction_ctrl_main_prev <- lme(fixed = y ~ lvl1_x * lvl2_x + popdens + rate_day,
                             random = ~ lvl1_x | lvl2_id, 
                         data = data,
                         correlation = corAR1(),
                    control = ctrl_config,
                  method = 'ML')
  
  
    # cross level interaction
    interaction_ctrl_int_prev<- lme(fixed = y ~ lvl1_x * lvl2_x + lvl1_x * popdens + rate_day,
                             random = ~ lvl1_x + rate_day | lvl2_id, 
                         data = data,
                         correlation = corAR1(),
                          control = ctrl_config,
                  method = 'ML')
  
    # create list with results
    results <- list('baseline' = baseline, 
                    "random_intercept" = random_intercept, 
                    "random_slope" = random_slope,
                    "interaction" = interaction,
                    "random_slope_ctrl_dem" = random_slope_ctrl_dem,
                    "interaction_ctrl_main_dem" = interaction_ctrl_main_dem,
                    "interaction_ctrl_int_dem" = interaction_ctrl_int_dem,                    
                    "random_slope_ctrl_prev" = random_slope_ctrl_prev,
                    "interaction_ctrl_main_prev" = interaction_ctrl_main_prev,
                    "interaction_ctrl_int_prev" = interaction_ctrl_int_prev)
  }
  
  if(ctrls == 'exp'){
    # random intercept random slope
  random_slope_exp <- lme(fixed = y ~ (lvl1_x + I(lvl1_x^2)) + lvl2_x, 
                      random = ~ (lvl1_x + I(lvl1_x^2)) | lvl2_id, 
                        data = data,
                        correlation = corAR1(),
                  control = ctrl_config,
                  method = 'ML')

  # cross level interaction
  interaction_exp <- lme(fixed = y ~ (lvl1_x + I(lvl1_x^2)) * lvl2_x, 
                     random = ~ (lvl1_x + I(lvl1_x^2)) | lvl2_id, 
                       data = data,
                       correlation = corAR1(),
                  control = ctrl_config,
                  method = 'ML')  
  
  
  # create list with results
  results <- list('baseline' = baseline, 
                  "random_intercept" = random_intercept, 
                  "random_slope" = random_slope,
                  "interaction" = interaction,                  
                  "random_slope_exp" = random_slope_exp,
                  "interaction_exp" = interaction_exp)
  }
  
  return(results)
        
}

# extracts table with coefficients and tests statistics
extract_results <- function(models) {
  
  models_summary <- models %>% 
  map(summary) %>% 
  map("tTable") %>% 
  map(as.data.frame) %>% 
  map(round, 10) 
  # %>% map(~ .[str_detect(rownames(.), 'Inter|lvl'),])
  
  return(models_summary)
  
}


# calculates comparison of all models in model list
compare_models <- function(models) {

  mdl_names <- models %>% names()
  
  str = ''
  for (i in mdl_names){
    
    mdl_str <- paste('models$', i, sep = '')
    
    if(i == 'baseline'){
      str <- mdl_str
    }else{
    str <- paste(str, mdl_str, sep=', ')
    }
  }
  
  anova_str <- paste0('anova(', str, ')')
  mdl_comp <- eval(parse(text=anova_str))
  rownames(mdl_comp) = mdl_names
  return(mdl_comp)
}

Remove London Data

# df_uk <- df_uk %>% filter(london == 'country')
# df_uk_socdist <- df_uk_socdist %>% filter(london == 'country')

Rescale Data

Adjust timeframes

Predict prevalence

prevalence ~ openness


models_o_covid <-run_models(y = 'rate_day', 
                         lvl1_x = 'time', 
                         lvl2_x = 'pers_o', 
                         lvl2_id = 'ut_area', 
                         data = df_uk_scaled_prev,
                         ctrls = 'dem')

extract_results(models_o_covid)

compare_models(models_o_covid)

prevalence ~ conscientiousness


models_c_covid <-run_models(y = 'rate_day', 
                         lvl1_x = 'time', 
                         lvl2_x = 'pers_c', 
                         lvl2_id = 'ut_area', 
                         data = df_uk_scaled_prev,
                         ctrls = 'dem')

extract_results(models_c_covid)

compare_models(models_c_covid)

prevalence ~ extraversion


models_e_covid <-run_models(y = 'rate_day', 
                         lvl1_x = 'time', 
                         lvl2_x = 'pers_e', 
                         lvl2_id = 'ut_area', 
                         data = df_uk_scaled_prev,
                         ctrls = 'dem')

extract_results(models_e_covid)

compare_models(models_e_covid)

prevalence ~ agreeableness


models_a_covid <-run_models(y = 'rate_day', 
                         lvl1_x = 'time', 
                         lvl2_x = 'pers_a', 
                         lvl2_id = 'ut_area', 
                         data = df_uk_scaled_prev,
                         ctrls = 'dem')

extract_results(models_a_covid)

compare_models(models_a_covid)

prevalence ~ neuroticism


models_n_covid <-run_models(y = 'rate_day', 
                         lvl1_x = 'time', 
                         lvl2_x = 'pers_n', 
                         lvl2_id = 'ut_area', 
                         data = df_uk_scaled_prev,
                         ctrls = 'dem')

extract_results(models_n_covid)

compare_models(models_n_covid)

Predict social distancing

social distancing ~ openness


models_o_socdist <-run_models(y = 'socdist_single_tile', 
                         lvl1_x = 'time', 
                         lvl2_x = 'pers_o', 
                         lvl2_id = 'nuts3', 
                         data = df_uk_socdist_scaled,
                         ctrls = 'prev')

extract_results(models_o_socdist)

compare_models(models_o_socdist)

social distancing ~ conscientiousness


models_c_socdist <-run_models(y = 'socdist_single_tile', 
                         lvl1_x = 'time', 
                         lvl2_x = 'pers_c', 
                         lvl2_id = 'nuts3', 
                         data = df_uk_socdist_scaled,
                         ctrls = 'prev')

extract_results(models_c_socdist)

compare_models(models_c_socdist)

social distancing ~ extraversion


models_e_socdist <-run_models(y = 'socdist_single_tile', 
                         lvl1_x = 'time', 
                         lvl2_x = 'pers_e', 
                         lvl2_id = 'nuts3', 
                         data = df_uk_socdist_scaled,
                         ctrls = 'prev')

extract_results(models_e_socdist)

compare_models(models_e_socdist)

social distancing ~ agreeableness


models_a_socdist <-run_models(y = 'socdist_single_tile', 
                         lvl1_x = 'time', 
                         lvl2_x = 'pers_a', 
                         lvl2_id = 'nuts3', 
                         data = df_uk_socdist_scaled,
                         ctrls = 'prev')

extract_results(models_a_socdist)

compare_models(models_a_socdist)

social distancing ~ neuroticism


models_n_socdist <-run_models(y = 'socdist_single_tile', 
                         lvl1_x = 'time', 
                         lvl2_x = 'pers_n', 
                         lvl2_id = 'nuts3', 
                         data = df_uk_socdist_scaled,
                         ctrls = 'prev')

extract_results(models_n_socdist)

compare_models(models_n_socdist)

prevalence ~ conscientiousness


models_c_covid_exp <-run_models(y = 'rate_day', 
                         lvl1_x = 'time', 
                         lvl2_x = 'pers_c', 
                         lvl2_id = 'ut_area', 
                         data = df_uk_scaled_prev,
                         ctrls = 'exp')

extract_results(models_c_covid_exp)

compare_models(models_c_covid_exp)

prevalence ~ extraversion


models_e_covid_exp <-run_models(y = 'rate_day', 
                         lvl1_x = 'time', 
                         lvl2_x = 'pers_e', 
                         lvl2_id = 'ut_area', 
                         data = df_uk_scaled_prev,
                         ctrls = 'exp')

extract_results(models_e_covid_exp)

compare_models(models_e_covid_exp)

prevalence ~ agreeableness


models_a_covid_exp <-run_models(y = 'rate_day', 
                         lvl1_x = 'time', 
                         lvl2_x = 'pers_a', 
                         lvl2_id = 'ut_area', 
                         data = df_uk_scaled_prev,
                         ctrls = 'exp')

extract_results(models_a_covid_exp)

compare_models(models_a_covid_exp)

prevalence ~ neuroticism


models_n_covid_exp <-run_models(y = 'rate_day', 
                         lvl1_x = 'time', 
                         lvl2_x = 'pers_n', 
                         lvl2_id = 'ut_area', 
                         data = df_uk_scaled_prev,
                         ctrls = 'exp')

extract_results(models_n_covid_exp)

compare_models(models_n_covid_exp)

Create overview table

Define function to create overview tables


summary_table <- function(models, dv_name, prev=F){

  temp_df_ctrl_main <- NULL
  temp_df_ctrl_int <- NULL
  temp_df_ctrl_int_prev <- NULL
  
  for (i in models){
    results <- i %>% extract_results()
    
    results_ctrl_main <- results$interaction_ctrl_main_dem['lvl1_x:lvl2_x',]
    temp_df_ctrl_main <- temp_df_ctrl_main %>% rbind(results_ctrl_main)
    
    results_ctrl_int <- results$interaction_ctrl_int_dem['lvl1_x:lvl2_x',]
    temp_df_ctrl_int <- temp_df_ctrl_int %>% rbind(results_ctrl_int)
    
    if(prev){
      results_ctrl_int_prev <- results$interaction_ctrl_int_prev['lvl1_x:lvl2_x',]
      temp_df_ctrl_int_prev <- temp_df_ctrl_int_prev %>% rbind(results_ctrl_int_prev)
    }
        
  }
  
  names_ctrl_main <- paste0(dv_name, '~', c('o', 'c', 'e', 'a', 'n'), '*time', '_crtl_popdens')
  rownames(temp_df_ctrl_main) <- names_ctrl_main

  names_ctrl_int <- paste0(dv_name, '~', c('o', 'c', 'e', 'a', 'n'), '*time', '_crtl_popdens*time')
  rownames(temp_df_ctrl_int) <- names_ctrl_int

  if(prev){
    names_ctrl_int_prev <- paste0(dv_name, '~', c('o', 'c', 'e', 'a', 'n'), '*time', '_crtl_popdens*time_prev')
    rownames(temp_df_ctrl_int_prev) <- names_ctrl_int_prev
    
    sum_tab <- rbind(temp_df_ctrl_main, temp_df_ctrl_int, temp_df_ctrl_int_prev) %>% round(4)
  }else{
    sum_tab <- rbind(temp_df_ctrl_main, temp_df_ctrl_int) %>% round(4)
  }


  
  return(sum_tab)

} 

Create overview tables

# prevalence
models_prev <- list(models_o_covid, 
                    models_c_covid, 
                    models_e_covid, 
                    models_a_covid, 
                    models_n_covid)

sum_tab_prev <- summary_table(models_prev, dv_name = 'prev')

write.table(sum_tab_prev, quote=F)

# social distancing
models_socdist <- list(models_o_socdist, 
                       models_c_socdist, 
                       models_e_socdist, 
                       models_a_socdist, 
                       models_n_socdist)

sum_tab_socdist <- summary_table(models_socdist, dv_name = 'socdist', prev=T)

write.table(sum_tab_socdist, quote=F)

Conditional random forest analysis

Extract slopes prevalence


# slope prevalence
df_uk_slope_prev <- df_uk_scaled_prev %>% split(.$ut_area) %>% 
  map(~ lm(rate_day ~ time, data = .)) %>%
  map(coef) %>% 
  map_dbl('time') %>% 
  as.data.frame() %>% 
  rownames_to_column('ut_area') %>% 
  rename(slope_prev = '.')

# merge with control variables 
df_uk_slope_prev <- df_uk_scaled_prev %>% select(-time, -rate_day) %>%
  distinct() %>% 
  inner_join(df_uk_slope_prev, by = 'ut_area') %>%
  drop_na()

head(df_uk_slope_prev)

Extract slopes social distancing


# slope socdist
df_uk_slope_socdist <- df_uk_socdist_scaled %>% split(.$nuts3) %>%
  map(~ lm(socdist_single_tile ~ time, data = .)) %>%
  map(coef) %>%
  map_dbl('time') %>%
  as.data.frame() %>%
  rownames_to_column('nuts3') %>%
  rename(slope_socdist = '.')

# merge with control variables 
df_uk_slope_socdist <- df_uk_socdist_scaled %>% 
  select(-time, -date, -socdist_tiles, -socdist_single_tile) %>%
  distinct() %>%
  inner_join(df_uk_slope_socdist, by = 'nuts3') %>%
  drop_na()

head(df_uk_slope_socdist)

Explore distribution of slopes

df_uk_slope_prev %>% ggplot(aes(slope_prev)) + geom_histogram(bins = 100)

df_uk_slope_socdist %>% ggplot(aes(slope_socdist)) + geom_histogram(bins = 100)
df_uk_slope_prev

CRF prevalence ~ openness


ctrls <- cforest_unbiased(ntree=500, mtry=5)

crf_o_fit_prev <- cforest(slope_prev ~ pers_o + airport_dist + males +
                          popdens + manufacturing + tourism +
                          health + academic + medinc + medage + conservative, 
                         df_uk_slope_prev[-1], 
                         controls = ctrls)

crf_o_varimp_prev <- varimp(crf_o_fit_prev, nperm = 1)
crf_o_varimp_cond_prev <- varimp(crf_o_fit_prev, conditional = T, nperm = 1)

crf_o_varimp_prev %>% as.data.frame() %>% rownames_to_column('variable') %>%
  ggplot(aes(x=variable, y=.)) +
  geom_bar(stat = 'identity') + 
  theme(axis.text.x = element_text(angle = 90))

crf_o_varimp_cond_prev %>% as.data.frame() %>% rownames_to_column('variable') %>%
  ggplot(aes(x=variable, y=.)) +
  geom_bar(stat = 'identity') +
  theme(axis.text.x = element_text(angle = 90))

CRF prevalence ~ conscientiousness


ctrls <- cforest_unbiased(ntree=500, mtry=5)

crf_c_fit_prev <- cforest(slope_prev ~ pers_c + airport_dist + males +
                          popdens + manufacturing + tourism +
                          health + academic + medinc + medage + conservative, 
                         df_uk_slope_prev[-1], 
                         controls = ctrls)

crf_c_varimp_prev <- varimp(crf_c_fit_prev, nperm = 1)
crf_c_varimp_cond_prev <- varimp(crf_c_fit_prev, conditional = T, nperm = 1)

crf_c_varimp_prev %>% as.data.frame() %>% rownames_to_column('variable') %>%
  ggplot(aes(x=variable, y=.)) +
  geom_bar(stat = 'identity') + 
  theme(axis.text.x = element_text(angle = 90))

crf_c_varimp_cond_prev %>% as.data.frame() %>% rownames_to_column('variable') %>%
  ggplot(aes(x=variable, y=.)) +
  geom_bar(stat = 'identity') + 
  theme(axis.text.x = element_text(angle = 90))

CRF prevalence ~ extraversion


ctrls <- cforest_unbiased(ntree=500, mtry=5)

crf_e_fit_prev <- cforest(slope_prev ~ pers_e + airport_dist + males +
                          popdens + manufacturing + tourism +
                          health + academic + medinc + medage + conservative, 
                         df_uk_slope_prev[-1], 
                         controls = ctrls)

crf_e_varimp_prev <- varimp(crf_e_fit_prev, nperm = 1)
crf_e_varimp_cond_prev <- varimp(crf_e_fit_prev, conditional = T, nperm = 1)

crf_e_varimp_prev %>% as.data.frame() %>% rownames_to_column('variable') %>%
  ggplot(aes(x=variable, y=.)) +
  geom_bar(stat = 'identity') + 
  theme(axis.text.x = element_text(angle = 90))

crf_e_varimp_cond_prev %>% as.data.frame() %>% rownames_to_column('variable') %>%
  ggplot(aes(x=variable, y=.)) +
  geom_bar(stat = 'identity') + 
  theme(axis.text.x = element_text(angle = 90))

CRF prevalence ~ agreeableness


ctrls <- cforest_unbiased(ntree=500, mtry=5)

crf_a_fit_prev <- cforest(slope_prev ~ pers_a + airport_dist + males +
                          popdens + manufacturing + tourism +
                          health + academic + medinc + medage + conservative, 
                         df_uk_slope_prev[-1], 
                         controls = ctrls)

crf_a_varimp_prev <- varimp(crf_a_fit_prev, nperm = 1)
crf_a_varimp_cond_prev <- varimp(crf_a_fit_prev, conditional = T, nperm = 1)

crf_a_varimp_prev %>% as.data.frame() %>% rownames_to_column('variable') %>%
  ggplot(aes(x=variable, y=.)) +
  geom_bar(stat = 'identity') + 
  theme(axis.text.x = element_text(angle = 90))

crf_a_varimp_cond_prev %>% as.data.frame() %>% rownames_to_column('variable') %>%
  ggplot(aes(x=variable, y=.)) +
  geom_bar(stat = 'identity') + 
  theme(axis.text.x = element_text(angle = 90))

CRF prevalence ~ neuroticism


ctrls <- cforest_unbiased(ntree=500, mtry=5)

crf_n_fit_prev <- cforest(slope_prev ~ pers_n + airport_dist + males +
                          popdens + manufacturing + tourism +
                          health + academic + medinc + medage + conservative, 
                         df_uk_slope_prev[-1], 
                         controls = ctrls)

crf_n_varimp_prev <- varimp(crf_n_fit_prev, nperm = 1)
crf_n_varimp_cond_prev <- varimp(crf_n_fit_prev, conditional = T, nperm = 1)

crf_n_varimp_prev %>% as.data.frame() %>% rownames_to_column('variable') %>%
  ggplot(aes(x=variable, y=.)) +
  geom_bar(stat = 'identity') + 
  theme(axis.text.x = element_text(angle = 90))

crf_n_varimp_cond_prev %>% as.data.frame() %>% rownames_to_column('variable') %>%
  ggplot(aes(x=variable, y=.)) +
  geom_bar(stat = 'identity') + 
  theme(axis.text.x = element_text(angle = 90))

CRF social distancing ~ openness


ctrls <- cforest_unbiased(ntree=500, mtry=5)

crf_o_fit_socdist <- cforest(slope_socdist ~ pers_o + airport_dist + males +
                          popdens + manufacturing + tourism +
                          health + academic + medinc + medage + conservative, 
                         df_uk_slope_socdist[-1], 
                         controls = ctrls)

crf_o_varimp_socdist <- varimp(crf_o_fit_socdist, nperm = 1)
crf_o_varimp_cond_socdist <- varimp(crf_o_fit_socdist, conditional = T, nperm = 1)

crf_o_varimp_socdist %>% as.data.frame() %>% rownames_to_column('variable') %>%
  ggplot(aes(x=variable, y=.)) +
  geom_bar(stat = 'identity') + 
  theme(axis.text.x = element_text(angle = 90))

crf_o_varimp_cond_socdist %>% as.data.frame() %>% rownames_to_column('variable') %>%
  ggplot(aes(x=variable, y=.)) +
  geom_bar(stat = 'identity') + 
  theme(axis.text.x = element_text(angle = 90))

CRF social distancing ~ conscientiousness


ctrls <- cforest_unbiased(ntree=500, mtry=5)

crf_c_fit_socdist <- cforest(slope_socdist ~ pers_c + airport_dist + males +
                          popdens + manufacturing + tourism +
                          health + academic + medinc + medage + conservative, 
                         df_uk_slope_socdist[-1], 
                         controls = ctrls)

crf_c_varimp_socdist <- varimp(crf_c_fit_socdist, nperm = 1)
crf_c_varimp_cond_socdist <- varimp(crf_c_fit_socdist, conditional = T, nperm = 1)

crf_c_varimp_socdist %>% as.data.frame() %>% rownames_to_column('variable') %>%
  ggplot(aes(x=variable, y=.)) +
  geom_bar(stat = 'identity') + 
  theme(axis.text.x = element_text(angle = 90))

crf_c_varimp_cond_socdist %>% as.data.frame() %>% rownames_to_column('variable') %>%
  ggplot(aes(x=variable, y=.)) +
  geom_bar(stat = 'identity') + 
  theme(axis.text.x = element_text(angle = 90))

CRF social distancing ~ extraversion


ctrls <- cforest_unbiased(ntree=500, mtry=5)

crf_e_fit_socdist <- cforest(slope_socdist ~ pers_e + airport_dist + males +
                          popdens + manufacturing + tourism +
                          health + academic + medinc + medage + conservative, 
                         df_uk_slope_socdist[-1], 
                         controls = ctrls)

crf_e_varimp_socdist <- varimp(crf_e_fit_socdist, nperm = 1)
crf_e_varimp_cond_socdist <- varimp(crf_e_fit_socdist, conditional = T, nperm = 1)

crf_e_varimp_socdist %>% as.data.frame() %>% rownames_to_column('variable') %>%
  ggplot(aes(x=variable, y=.)) +
  geom_bar(stat = 'identity') + 
  theme(axis.text.x = element_text(angle = 90))

crf_e_varimp_cond_socdist %>% as.data.frame() %>% rownames_to_column('variable') %>%
  ggplot(aes(x=variable, y=.)) +
  geom_bar(stat = 'identity') + 
  theme(axis.text.x = element_text(angle = 90))

CRF social distancing ~ agreeableness


ctrls <- cforest_unbiased(ntree=500, mtry=5)

crf_a_fit_socdist <- cforest(slope_socdist ~ pers_a + airport_dist + males +
                          popdens + manufacturing + tourism +
                          health + academic + medinc + medage + conservative, 
                         df_uk_slope_socdist[-1], 
                         controls = ctrls)

crf_a_varimp_socdist <- varimp(crf_a_fit_socdist, nperm = 1)
crf_a_varimp_cond_socdist <- varimp(crf_a_fit_socdist, conditional = T, nperm = 1)

crf_a_varimp_socdist %>% as.data.frame() %>% rownames_to_column('variable') %>%
  ggplot(aes(x=variable, y=.)) +
  geom_bar(stat = 'identity') + 
  theme(axis.text.x = element_text(angle = 90))

crf_a_varimp_cond_socdist %>% as.data.frame() %>% rownames_to_column('variable') %>%
  ggplot(aes(x=variable, y=.)) +
  geom_bar(stat = 'identity') + 
  theme(axis.text.x = element_text(angle = 90))

CRF social distancing ~ neuroticism


ctrls <- cforest_unbiased(ntree=500, mtry=5)

crf_n_fit_socdist <- cforest(slope_socdist ~ pers_n + airport_dist + males +
                          popdens + manufacturing + tourism +
                          health + academic + medinc + medage + conservative, 
                         df_uk_slope_socdist[-1], 
                         controls = ctrls)

crf_n_varimp_socdist <- varimp(crf_n_fit_socdist, nperm = 1)
crf_n_varimp_cond_socdist <- varimp(crf_n_fit_socdist, conditional = T, nperm = 1)

crf_n_varimp_socdist %>% as.data.frame() %>% rownames_to_column('variable') %>%
  ggplot(aes(x=variable, y=.)) +
  geom_bar(stat = 'identity') + 
  theme(axis.text.x = element_text(angle = 90))

crf_n_varimp_cond_socdist %>% as.data.frame() %>% rownames_to_column('variable') %>%
  ggplot(aes(x=variable, y=.)) +
  geom_bar(stat = 'identity') + 
  theme(axis.text.x = element_text(angle = 90))

Change point analysis

Preparation


# keep only counties with full data
ut_area_complete <- df_uk_scaled %>% 
  group_by(ut_area) %>%
  summarize(n = n()) %>%
  filter(n==max(.$n)) %>% 
  .$ut_area

Prevalence

df_uk_cpt_prev %>% select(cpt_day_prev) %>% map(hist)
$cpt_day_prev
$breaks
[1] 20 25 30 35 40 45 50

$counts
[1] 107   0   5  14  21   2

$density
[1] 0.143624161 0.000000000 0.006711409 0.018791946 0.028187919 0.002684564

$mids
[1] 22.5 27.5 32.5 37.5 42.5 47.5

$xname
[1] ".x[[i]]"

$equidist
[1] TRUE

attr(,"class")
[1] "histogram"

Social distancing


for(i in head(df_uk_socdist_cpt_results,5)){
  plot(i)
}

Predicting change points

Linear models predicting change points (no controls)


lm_cpr_prev_pers <- lm(cpt_day_prev ~ pers_o + pers_c + pers_e + pers_a + pers_n, 
                         data = df_uk_cpt_prev_socdist)
lm_cpr_prev_pers %>% summary()


lm_cpt_socdist_pers <- lm(cpt_day_socdist ~ pers_o + pers_c + pers_e + pers_a + pers_n, 
                            data = df_uk_cpt_prev_socdist)
lm_cpt_socdist_pers %>% summary()

Linear models predicting change points with controls

df_uk_cpt_prev_socdist

lm_cpt_prev_pers <- lm(cpt_day_prev ~ pers_o + pers_c + pers_e + pers_a + pers_n + 
                         women + academics + hospital_beds + gdp + manufact +
                          airport + age + popdens,
                         data = df_uk_cpt_prev_socdist)
lm_cpt_prev_pers %>% summary()

lm_cpt_socdist_pers <- lm(cpt_day_socdist ~ pers_o + pers_c + pers_e + pers_a + pers_n + 
                            women + academics + hospital_beds + gdp + manufact +
                            airport + age + popdens,
                            data = df_uk_cpt_prev_socdist)
lm_cpt_socdist_pers %>% summary()
LS0tCnRpdGxlOiAiQ09WSUQxOSBVSyIKYXV0aG9yOiAiSGVpbnJpY2ggUGV0ZXJzIgpkYXRlOiAiNC8yMy8yMDIwIgpvdXRwdXQ6IGh0bWxfbm90ZWJvb2sKLS0tCgoKYGBge3Igc2V0dXAsIGluY2x1ZGU9RkFMU0V9CmtuaXRyOjpvcHRzX2NodW5rJHNldChlY2hvID0gVFJVRSkKCiMgTUFDCiBrbml0cjo6b3B0c19rbml0JHNldChyb290LmRpciA9ICcvVXNlcnMvaHAyNTAwL0dvb2dsZSBEcml2ZS9TVFVEWS9Db2x1bWJpYS9SZXNlYXJjaC9Db3JvbmEvRGF0YS9VSycpCiAKbGlicmFyeShsbWVyVGVzdCkKbGlicmFyeShubG1lKQpsaWJyYXJ5KHBzeWNoKQpsaWJyYXJ5KGdncGxvdDIpCmxpYnJhcnkoZHBseXIpCmxpYnJhcnkodGlkeXZlcnNlKQpsaWJyYXJ5KHh0YWJsZSkKCmBgYAoKIyBQcmVwYXJlIGRhdGEKCiMjIyBSZWFkIGFuZCBmb3JtYXQgZGF0YQoKIyMjIFByZXZhbGVuY2UgCgpgYGB7cn0KZGZfdWtfcHJldiA8LSByZWFkX2NzdignVUtfdGltZXNlcmllc19wcmVwXzIwMDUuY3N2JykKCmRmX3VrX3ByZXYgPC0gZGZfdWtfcHJldiAlPiUgCiAgc2VsZWN0KHV0X2FyZWEsIGRhdGUsIHJhdGUpICU+JSAKICByZW5hbWUocmF0ZV9kYXkgPSByYXRlKSAlPiUKICBtdXRhdGUoZGF0ZSA9IGFzLkRhdGUoZGF0ZSwgIiVkJWIlWSIpKQoKZGZfdWtfcHJldgpgYGAKCiMjIyBQZXJzb25hbGl0eQpgYGB7cn0KCmRmX3VrX3BlcnMgPC0gcmVhZF9jc3YoJ3RpbWVzZXJpZXNfdWtfdXRsYV9tYXJjaDlfYXByaWxfMDkuY3N2JykKCmRmX3VrX3BlcnMgPC0gZGZfdWtfcGVycyAlPiUgCiAgc2VsZWN0KHV0X2FyZWEsIG9wZW4sIGFncmVlLCBuZXVybywgc2NpLCBleHRyYSkgJT4lIAogIGRwbHlyOjpyZW5hbWUocGVyc19vID0gb3BlbiwgCiAgICAgICAgIHBlcnNfYyA9IHNjaSwKICAgICAgICAgcGVyc19lID0gZXh0cmEsCiAgICAgICAgIHBlcnNfYSA9IGFncmVlLAogICAgICAgICBwZXJzX24gPSBuZXVybykgJT4lCiAgZGlzdGluY3QoKQoKZGZfdWtfcGVycwoKYGBgCgojIyMgU29jaWFsIGRpc3RhbmNpbmcKYGBge3J9CmRmX3VrX3NvY2Rpc3QgPC0gcmVhZF9jc3YoJ1VLX3NvY2Rpc3RfZmJfbnV0czMuY3N2JykKZGZfdWtfc29jZGlzdCRkYXRlICU+JSBzdW1tYXJ5KCkKCmRmX3VrX3NvY2Rpc3QgPC0gZGZfdWtfc29jZGlzdCAlPiUgc2VsZWN0KC1ydW5kYXksIC1mcmVxdSkgJT4lCiAgZHBseXI6OnJlbmFtZShwZXJzX28gPSBvcGVuLCAKICAgICAgICAgICAgICAgIHBlcnNfYyA9IHNjaSwKICAgICAgICAgICAgICAgIHBlcnNfZSA9IGV4dHJhLAogICAgICAgICAgICAgICAgcGVyc19hID0gYWdyZWUsCiAgICAgICAgICAgICAgICBwZXJzX24gPSBuZXVybykgJT4lIAogIHNlbGVjdCgtbnV0czNfbmFtZSkgJT4lIAogIGRwbHlyOjpyZW5hbWUoc29jZGlzdF90aWxlcyA9IGFsbF9kYXlfYmluZ190aWxlc192aXNpdGVkX3JlbGF0LAogICAgICAgICAgICAgICAgc29jZGlzdF9zaW5nbGVfdGlsZSA9IGFsbF9kYXlfcmF0aW9fc2luZ2xlX3RpbGVfdXNlcnMpICU+JQogIGRyb3BfbmEoKQoKZGZfdWtfc29jZGlzdApgYGAKCiMjIyBDb250cm9scyAKYGBge3J9CmRmX3VrX2N0cmxfbnV0cyA8LSByZWFkX2NzdigiY29udHJvbHNfVUtfbnV0czMuY3N2IikKZGZfdWtfY3RybF9udXRzIDwtIGRmX3VrX2N0cmxfbnV0cyAlPiUgc2VsZWN0KC1udXRzM19uYW1lKQpkZl91a19jdHJsX251dHMKCgpkZl91a19jdHJsX3V0IDwtIHJlYWRfY3N2KCJjb250cm9sc19VS191dC5jc3YiKQpkZl91a19jdHJsX3V0IDwtIGRmX3VrX2N0cmxfdXQgJT4lIHNlbGVjdCgtdXRfbmFtZSkKZGZfdWtfY3RybF91dAoKCmBgYAoKCgoKCiMjIyBNZXJnZSBwcmV2YWxlbmNlIGRhdGEgCmBgYHtyfQpkZl91ayA8LSBkZl91a19wcmV2ICU+JSAKICBwbHlyOjpqb2luKGRmX3VrX3BlcnMsIGJ5PSd1dF9hcmVhJykgJT4lIAogIHBseXI6OmpvaW4oZGZfdWtfY3RybF91dCwgYnk9J3V0X2FyZWEnKQoKIyBjcmVhdGUgc2VxdWVuY2Ugb2YgZGF0ZXMKZGF0ZV9zZXF1ZW5jZSA8LSBzZXEuRGF0ZShtaW4oZGZfdWskZGF0ZSksCiAgICAgICAgICAgICAgICAgICAgICAgICAgbWF4KGRmX3VrJGRhdGUpLCAxKQogICAgICAgICAgICAgICAgICAgICAKIyBjcmVhdGUgZGF0YSBmcmFtZSB3aXRoIHRpbWUgc2VxdWVuY2UKZGZfZGF0ZXMgPSB0aWJibGUoZGF0ZV9zZXF1ZW5jZSwgMTpsZW5ndGgoZGF0ZV9zZXF1ZW5jZSkpIApuYW1lcyhkZl9kYXRlcykgPC0gYygnZGF0ZScsICd0aW1lJykKCiMgbWVyZ2UgZGF5IGluZGV4IHdpdGggZ3BzIGRhdGEKZGZfdWsgPSBkZl91ayAlPiUgCiAgbWVyZ2UoZGZfZGF0ZXMsIGJ5PSdkYXRlJykgJT4lIAogIGFycmFuZ2UodXRfYXJlYSkgJT4lCiAgYXNfdGliYmxlKCkKCmRmX3VrCmBgYAoKIyMjIE1lcmdlIHNvY2lhbCBkaXN0YW5jaW5nIGRhdGEKYGBge3J9CgpudXRzX3V0X2tleSA8LSByZWFkX2NzdignbnV0czNfdXQuY3N2JykKZGZfdWtfc29jZGlzdCA8LSBkZl91a19zb2NkaXN0ICU+JSBwbHlyOjpqb2luKGRmX3VrX2N0cmxfbnV0cywgYnk9J251dHMzJykKCmRmX3VrX3NvY2Rpc3QgPC0gbnV0c191dF9rZXkgJT4lIAogIGlubmVyX2pvaW4oZGZfdWtfc29jZGlzdCwgYnkgPSBjKCdudXRzMycpKSAlPiUKICBpbm5lcl9qb2luKHNlbGVjdChkZl91aywgdXRfYXJlYSwgZGF0ZSwgcmF0ZV9kYXkpLCBieSA9IGMoJ3V0X2FyZWEnLCAnZGF0ZScpKSAlPiUKICBzZWxlY3QoLXV0X2FyZWEpCgojIGNyZWF0ZSBzZXF1ZW5jZSBvZiBkYXRlcwpkYXRlX3NlcXVlbmNlIDwtIHNlcS5EYXRlKG1pbihkZl91a19zb2NkaXN0JGRhdGUpLAogICAgICAgICAgICAgICAgICAgICAgICAgIG1heChkZl91a19zb2NkaXN0JGRhdGUpLCAxKQogICAgICAgICAgICAgICAgICAgICAKIyBjcmVhdGUgZGF0YSBmcmFtZSB3aXRoIHRpbWUgc2VxdWVuY2UKZGZfZGF0ZXMgPSB0aWJibGUoZGF0ZV9zZXF1ZW5jZSwgMTpsZW5ndGgoZGF0ZV9zZXF1ZW5jZSkpIApuYW1lcyhkZl9kYXRlcykgPC0gYygnZGF0ZScsICd0aW1lJykKCiMgbWVyZ2UgZGF5IGluZGV4IHdpdGggZ3BzIGRhdGEKZGZfdWtfc29jZGlzdCA9IGRmX3VrX3NvY2Rpc3QgJT4lIAogIG1lcmdlKGRmX2RhdGVzLCBieT0nZGF0ZScpICU+JSAKICBhcnJhbmdlKG51dHMzKSAlPiUKICBhc190aWJibGUoKQoKCmRmX3VrX3NvY2Rpc3QKCmBgYAoKCiMjIyBJZGVudGlmeSBMb25kb24gYXJlYXMKYGBge3J9CgpudXRzX2xvbmRvbl9pbm5lciA8LSBjKCdVS0kzMScsJ1VLSTMyJywnVUtJMzMnLCdVS0kzNCcsJ1VLSTQxJywKICAgICAgICAgICAgICAgICAgICAgICdVS0k0MicsJ1VLSTQzJywnVUtJNDQnLCdVS0k0NScpCgpudXRzX2xvbmRvbl9vdXRlciA8LSBjKCdVS0k1MScsJ1VLSTUyJywnVUtJNTMnLCdVS0k1NCcsJ1VLSTYxJywKICAgICAgICAgICAgICAgICAgICAgICdVS0k2MicsJ1VLSTYzJywnVUtJNzEnLCdVS0k3MicsJ1VLSTczJywKICAgICAgICAgICAgICAgICAgICAgICdVS0k3NCcsJ1VLSTc1JykKCnV0X2xvbmRvbl9pbm5lciA8LSBjKCdFMDkwMDAwMDcnLCdFMDkwMDAwMDEnLCdFMDkwMDAwMzMnLCdFMDkwMDAwMTMnLAogICAgICAgICAgICAgICAgICAgICdFMDkwMDAwMjAnLCdFMDkwMDAwMzInLCdFMDkwMDAwMjUnLCdFMDkwMDAwMTInLAogICAgICAgICAgICAgICAgICAgICdFMDkwMDAwMzAnLCdFMDkwMDAwMTQnLCdFMDkwMDAwMTknLCdFMDkwMDAwMjMnLAogICAgICAgICAgICAgICAgICAgICdFMDkwMDAwMjgnLCdFMDkwMDAwMjInKQoKdXRfbG9uZG9uX291dGVyIDwtIGMoJ0UwOTAwMDAxMScsJ0UwOTAwMDAwNCcsJ0UwOTAwMDAxNicsJ0UwOTAwMDAwMicsCiAgICAgICAgICAgICAgICAgICAgJ0UwOTAwMDAzMScsJ0UwOTAwMDAyNicsJ0UwOTAwMDAxMCcsJ0UwOTAwMDAwNicsCiAgICAgICAgICAgICAgICAgICAgJ0UwOTAwMDAwOCcsJ0UwOTAwMDAyOScsJ0UwOTAwMDAyMScsJ0UwOTAwMDAyNCcsCiAgICAgICAgICAgICAgICAgICAgJ0UwOTAwMDAwMycsJ0UwOTAwMDAwNScsJ0UwOTAwMDAwOScsJ0UwOTAwMDAxNycsCiAgICAgICAgICAgICAgICAgICAgJ0UwOTAwMDAxNScsJ0UwOTAwMDAxOCcsJ0UwOTAwMDAyNycpCmBgYAoKYGBge3J9CgpkZl91ayA9IGRmX3VrICU+JSAKICBtdXRhdGUobG9uZG9uID0gaWZlbHNlKHV0X2FyZWEgJWluJSB1dF9sb25kb25faW5uZXIsICdsb25kb25faW5uZXInLCAKICAgICAgICAgICAgICAgICAgICAgICBpZmVsc2UodXRfYXJlYSAlaW4lIHV0X2xvbmRvbl9vdXRlciwgJ2xvbmRvbl9vdXRlcicsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICdjb3VudHJ5JykpKSAlPiUKICBtdXRhdGUobG9uZG9uID0gYXMuZmFjdG9yKGxvbmRvbikpCgpkZl91a19zb2NkaXN0ID0gZGZfdWtfc29jZGlzdCAlPiUgCiAgbXV0YXRlKGxvbmRvbiA9IGlmZWxzZShudXRzMyAlaW4lIG51dHNfbG9uZG9uX2lubmVyLCAnbG9uZG9uX2lubmVyJywgCiAgICAgICAgICAgICAgICAgICAgICAgaWZlbHNlKG51dHMzICVpbiUgbnV0c19sb25kb25fb3V0ZXIsICdsb25kb25fb3V0ZXInLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAnY291bnRyeScpKSkgJT4lCiAgbXV0YXRlKGxvbmRvbiA9IGFzLmZhY3Rvcihsb25kb24pKQoKYGBgCgoKIyBFeHBsb3JlIGRhdGEKCiMjIyBQbG90IHByZXZhbGVuY2Ugb3ZlciB0aW1lCmBgYHtyfQoKZGZfdWsgJT4lIGdncGxvdChhZXMoeD10aW1lLCB5PXJhdGVfZGF5KSkgKyAKICBnZW9tX3BvaW50KGFlcyhjb2w9dXRfYXJlYSwgc2l6ZT1wb3BkZW5zKSkgKyAKICBnZW9tX3Ntb290aChtZXRob2Q9ImxvZXNzIiwgc2U9VCkgKyAKICB0aGVtZShsZWdlbmQucG9zaXRpb249Im5vbmUiKSArCiAgZ2d0aXRsZSgiT3ZlcmFsbCBwcmV2YWxlbmNlIG92ZXIgdGltZSIpCgpwZXJzIDwtIGMoJ3BlcnNfbycsICdwZXJzX2MnLCAncGVyc19lJywgJ3BlcnNfYScsICdwZXJzX24nKQoKZm9yIChpIGluIHBlcnMpewoKZ2cgPC0gZGZfdWsgJT4lIG11dGF0ZShwcmV2X3RhaWwgPSBjdXQoLltbaV1dLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWtzID0gYygtSW5mLCBxdWFudGlsZSguW1tpXV0sIDAuMiksIHF1YW50aWxlKC5bW2ldXSwgMC44KSwgSW5mKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGFiZWxzID0gYygnbG93ZXIgdGFpbCcsICdjZW50ZXInLCAndXBwZXIgdGFpbCcpKSkgJT4lIAogIGZpbHRlcihwcmV2X3RhaWwgIT0gJ2NlbnRlcicpICU+JQogIGdncGxvdChhZXMoeD10aW1lLCB5PXJhdGVfZGF5KSkgKyAKICBnZW9tX3BvaW50KGFlcyhjb2w9dXRfYXJlYSwgc2l6ZT1wb3BkZW5zKSkgKyAKICBnZW9tX3Ntb290aChtZXRob2Q9ImxvZXNzIiwgc2U9VCkgKyAKICBmYWNldF93cmFwKH5wcmV2X3RhaWwpICsgCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uPSJub25lIikgKwogIGdndGl0bGUoaSkKCnByaW50KGdnKQp9CgpgYGAKCgojIyMgUGxvdCBzb2NpYWwgZGlzdGFuY2luZyBvdmVyIHRpbWUKYGBge3J9CgpkZl91a19zb2NkaXN0ICU+JSBnZ3Bsb3QoYWVzKHg9dGltZSwgeT1zb2NkaXN0X3NpbmdsZV90aWxlKSkgKyAKICBnZW9tX3BvaW50KGFlcyhjb2w9bnV0czMsIHNpemU9cG9wZGVucykpICsgCiAgZ2VvbV9zbW9vdGgobWV0aG9kPSJsb2VzcyIsIHNlPVQpICsgCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uPSJub25lIikgKwogIGdndGl0bGUoIk92ZXJhbGwgc29jaWFsIGRpc3RhbmNpbmcgb3ZlciB0aW1lIikKCnBlcnMgPC0gYygncGVyc19vJywgJ3BlcnNfYycsICdwZXJzX2UnLCAncGVyc19hJywgJ3BlcnNfbicpCgpmb3IgKGkgaW4gcGVycyl7CgpnZyA8LSBkZl91a19zb2NkaXN0ICU+JSBtdXRhdGUoc29jZGlzdF90YWlsID0gY3V0KC5bW2ldXSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrcyA9IGMoLUluZiwgcXVhbnRpbGUoLltbaV1dLCAwLjIpLCBxdWFudGlsZSguW1tpXV0sIDAuOCksIEluZiksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxhYmVscyA9IGMoJ2xvd2VyIHRhaWwnLCAnY2VudGVyJywgJ3VwcGVyIHRhaWwnKSkpICU+JSAKICBmaWx0ZXIoc29jZGlzdF90YWlsICE9ICdjZW50ZXInKSAlPiUKICBnZ3Bsb3QoYWVzKHg9dGltZSwgeT1zb2NkaXN0X3NpbmdsZV90aWxlKSkgKyAKICBnZW9tX3BvaW50KGFlcyhjb2w9bnV0czMsIHNpemU9cG9wZGVucykpICsgCiAgZ2VvbV9zbW9vdGgobWV0aG9kPSJsb2VzcyIsIHNlPVQpICsgCiAgZmFjZXRfd3JhcCh+c29jZGlzdF90YWlsKSArIAogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbj0ibm9uZSIpICsKICBnZ3RpdGxlKGkpCgpwcmludChnZykKfQoKYGBgCgojIyMgRXhwbG9yZSBkaWZmZXJlbmNlcyBiZXR3ZWVuIGxvbmRvbiBhbmQgdGhlIHJlc3QgCmBgYHtyfQoKZGZfdWsgJT4lIGdncGxvdChhZXMoeD10aW1lLCB5PXJhdGVfZGF5KSkgKyAKICBnZW9tX3BvaW50KGFlcyhjb2w9dXRfYXJlYSwgc2l6ZT1wb3BkZW5zKSkgKyAKICBnZW9tX3Ntb290aChtZXRob2Q9ImxvZXNzIiwgc2U9VCkgKyAKICB0aGVtZShsZWdlbmQucG9zaXRpb249Im5vbmUiKSArCiAgZmFjZXRfd3JhcCh+bG9uZG9uKSArCiAgZ2d0aXRsZSgiT3ZlcmFsbCBwcmV2YWxlbmNlIG92ZXIgdGltZSIpCgoKCmBgYAoKCmBgYHtyfQpkZl91a19zb2NkaXN0ICU+JSBnZ3Bsb3QoYWVzKHg9dGltZSwgeT1zb2NkaXN0X3NpbmdsZV90aWxlKSkgKyAKICBnZW9tX3BvaW50KGFlcyhjb2w9bnV0czMsIHNpemU9cG9wZGVucykpICsgCiAgZ2VvbV9zbW9vdGgobWV0aG9kPSJsb2VzcyIsIHNlPVQpICsgCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uPSJub25lIikgKwogIGZhY2V0X3dyYXAofmxvbmRvbikgKwogIGdndGl0bGUoIk92ZXJhbGwgc29jaWFsIGRpc3RhbmNpbmcgb3ZlciB0aW1lIikKYGBgCgojIyMgQ29udHJvbCBmb3Igd2Vla2VuZCBlZmZlY3QgCmBgYHtyfQoKZGZfdWtfbG9lc3MgPC0gZGZfdWtfc29jZGlzdCAlPiUgCiAgbXV0YXRlKHdlZWtkYXkgPSBmb3JtYXQoZGF0ZSwgJyV1JykpICU+JSAKICBmaWx0ZXIoIXdlZWtkYXkgJWluJSBjKCc2JywnNycpKSAlPiUgCiAgc3BsaXQoLiRudXRzMykgJT4lCiAgbWFwKH4gbG9lc3Moc29jZGlzdF9zaW5nbGVfdGlsZSB+IHRpbWUsIGRhdGEgPSAuKSkgJT4lCiAgbWFwKHByZWRpY3QsIDE6bWF4KGRmX3VrX3NvY2Rpc3QkdGltZSkpICU+JSAKICBiaW5kX3Jvd3MoKSAlPiUgCiAgZ2F0aGVyKGtleSA9ICdudXRzMycsIHZhbHVlID0gJ2xvZXNzJykgJT4lIAogIGdyb3VwX2J5KG51dHMzKSAlPiUgCiAgbXV0YXRlKHRpbWUgPSByb3dfbnVtYmVyKCkpCgpkZl91a19sb2VzcwoKZGZfdWtfc29jZGlzdCA8LSBkZl91a19zb2NkaXN0ICU+JSBtZXJnZShkZl91a19sb2VzcywgYnk9YygnbnV0czMnLCAndGltZScpKSAlPiUgCiAgbXV0YXRlKHdlZWtkYXkgPSBmb3JtYXQoZGF0ZSwgJyV1JykpICU+JSAKICBtdXRhdGUoc29jZGlzdF9zaW5nbGVfdGlsZV9jbGVhbiA9IGlmZWxzZSh3ZWVrZGF5ICVpbiUgYygnNicsJzcnKSwgbG9lc3MsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc29jZGlzdF9zaW5nbGVfdGlsZSkpICU+JQogIGFycmFuZ2UobnV0czMsIHRpbWUpICU+JSAKICBzZWxlY3QoLXdlZWtkYXkpCgoKZGZfdWtfc29jZGlzdCA8LSBkZl91a19zb2NkaXN0ICU+JSBkcm9wX25hKCkgJT4lIG11dGF0ZSh0aW1lID0gdGltZS0xKQoKYGBgCgoKYGBge3J9CgpkZl91a19zb2NkaXN0ICU+JSBnZ3Bsb3QoYWVzKHg9dGltZSwgeT1zb2NkaXN0X3NpbmdsZV90aWxlX2NsZWFuKSkgKyAKICBnZW9tX3BvaW50KGFlcyhjb2w9bnV0czMsIHNpemU9cG9wZGVucykpICsgCiAgZ2VvbV9zbW9vdGgobWV0aG9kPSJsb2VzcyIsIHNlPVQpICsgCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uPSJub25lIikgKwogIGdndGl0bGUoIk92ZXJhbGwgc29jaWFsIGRpc3RhbmNpbmcgb3ZlciB0aW1lIikKCnBlcnMgPC0gYygncGVyc19vJywgJ3BlcnNfYycsICdwZXJzX2UnLCAncGVyc19hJywgJ3BlcnNfbicpCgpmb3IgKGkgaW4gcGVycyl7CgpnZyA8LSBkZl91a19zb2NkaXN0ICU+JSBtdXRhdGUoc29jZGlzdF90YWlsID0gY3V0KC5bW2ldXSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrcyA9IGMoLUluZiwgcXVhbnRpbGUoLltbaV1dLCAwLjIpLCBxdWFudGlsZSguW1tpXV0sIDAuOCksIEluZiksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxhYmVscyA9IGMoJ2xvd2VyIHRhaWwnLCAnY2VudGVyJywgJ3VwcGVyIHRhaWwnKSkpICU+JSAKICBmaWx0ZXIoc29jZGlzdF90YWlsICE9ICdjZW50ZXInKSAlPiUKICBnZ3Bsb3QoYWVzKHg9dGltZSwgeT1zb2NkaXN0X3NpbmdsZV90aWxlX2NsZWFuKSkgKyAKICBnZW9tX3BvaW50KGFlcyhjb2w9bnV0czMsIHNpemU9cG9wZGVucykpICsgCiAgZ2VvbV9zbW9vdGgobWV0aG9kPSJsb2VzcyIsIHNlPVQpICsgCiAgZmFjZXRfd3JhcCh+c29jZGlzdF90YWlsKSArIAogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbj0ibm9uZSIpICsKICBnZ3RpdGxlKGkpCgpwcmludChnZykKfQoKYGBgCgpgYGB7cn0KCmRmX3VrX3NvY2Rpc3QgPC0gZGZfdWtfc29jZGlzdCAlPiUgbXV0YXRlKHNvY2Rpc3Rfc2luZ2xlX3RpbGUgPSBzb2NkaXN0X3NpbmdsZV90aWxlX2NsZWFuKSAlPiUgCiAgc2VsZWN0KC1sb2VzcywgLXNvY2Rpc3Rfc2luZ2xlX3RpbGVfY2xlYW4pCgpgYGAKCiMjIyBDb3JyZWxhdGlvbnMKYGBge3J9CgpkZl91ayAlPiUgZ3JvdXBfYnkodXRfYXJlYSkgJT4lIAogIHN1bW1hcml6ZV9pZihpcy5udW1lcmljLCBtZWFuLCBuYS5ybT1UKSAlPiUgCiAgc2VsZWN0KC11dF9hcmVhLCAtdGltZSkgJT4lIAogIGNvcih1c2UgPSAncGFpcndpc2UuY29tcGxldGUnKSAlPiUgcm91bmQoMykKCmRmX3VrX3NvY2Rpc3QgJT4lIGdyb3VwX2J5KG51dHMzKSAlPiUgCiAgc3VtbWFyaXplX2lmKGlzLm51bWVyaWMsIG1lYW4sIG5hLnJtPVQpICU+JSAKICBzZWxlY3QoLW51dHMzLCAtdGltZSkgJT4lIAogIGNvcih1c2UgPSAncGFpcndpc2UuY29tcGxldGUnKSAlPiUgcm91bmQoMykKCmBgYAoKIyBNb2RlbGxpbmcgCiMjIFByZXBhcmUgZnVuY3Rpb25zCgpgYGB7cn0KCiMgZnVuY3Rpb24gY2FsY3VsYXRlcyBhbGwgcmVsZXZhbnQgbW9kZWxzCnJ1bl9tb2RlbHMgPC0gZnVuY3Rpb24oeSwgbHZsMV94LCBsdmwyX3gsIGx2bDJfaWQsIGRhdGEsIGN0cmxzPUYpewoKICAjIHN1YnNldCBkYXRhCiAgZGF0YSA9IGRhdGEgJT4lIAogICAgZHBseXI6OnNlbGVjdChhbGxfb2YoeSksIGFsbF9vZihsdmwxX3gpLCBhbGxfb2YobHZsMl94KSwgYWxsX29mKGx2bDJfaWQpLCAKICAgICAgICAgICAgICAgICAgcG9wZGVucywgcmF0ZV9kYXksIGFsbF9vZih5KSkKICBkYXRhID0gZGF0YSAlPiUgCiAgICBkcGx5cjo6cmVuYW1lKHkgPSBhbGxfb2YoeSksCiAgICAgICAgICAgbHZsMV94ID0gYWxsX29mKGx2bDFfeCksCiAgICAgICAgICAgbHZsMl94ID0gYWxsX29mKGx2bDJfeCksCiAgICAgICAgICAgbHZsMl9pZCA9IGFsbF9vZihsdmwyX2lkKQogICAgICAgICAgICkKICAKICAjIGNvbmZpZ3VyZSBvcHRpbWl6YXRpb24gcHJvY2VkdXJlCiAgY3RybF9jb25maWcgPC0gbG1lQ29udHJvbChvcHQgPSAnb3B0aW0nLCBtYXhJdGVyID0gMTAwLCBtc01heEl0ZXIgPSAxMDApCgogICMgYmFzZWxpbmUKICBiYXNlbGluZSA8LSBsbWUoZml4ZWQgPSB5IH4gMSwgcmFuZG9tID0gfiAxIHwgbHZsMl9pZCwgCiAgICAgICAgICAgICAgICAgICAgZGF0YSA9IGRhdGEsCiAgICAgICAgICAgICAgICAgICAgY29ycmVsYXRpb24gPSBjb3JBUjEoKSwKICAgICAgICAgICAgICAgICAgY29udHJvbCA9IGN0cmxfY29uZmlnLAogICAgICAgICAgICAgICAgICBtZXRob2QgPSAnTUwnKQoKICAjIHJhbmRvbSBpbnRlcmNlcHQgZml4ZWQgc2xvcGUKICByYW5kb21faW50ZXJjZXB0IDwtIGxtZShmaXhlZCA9IHkgfiBsdmwxX3ggKyBsdmwyX3gsIAogICAgICAgICAgICAgICAgICAgICAgICAgIHJhbmRvbSA9IH4gMSB8IGx2bDJfaWQsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBkYXRhID0gZGF0YSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvcnJlbGF0aW9uID0gY29yQVIxKCksCiAgICAgICAgICAgICAgICAgIGNvbnRyb2wgPSBjdHJsX2NvbmZpZywKICAgICAgICAgICAgICAgICAgbWV0aG9kID0gJ01MJykKCiAgIyByYW5kb20gaW50ZXJjZXB0IHJhbmRvbSBzbG9wZQogIHJhbmRvbV9zbG9wZSA8LSBsbWUoZml4ZWQgPSB5IH4gbHZsMV94ICsgbHZsMl94LCAKICAgICAgICAgICAgICAgICAgICAgIHJhbmRvbSA9IH4gbHZsMV94IHwgbHZsMl9pZCwgCiAgICAgICAgICAgICAgICAgICAgICAgIGRhdGEgPSBkYXRhLAogICAgICAgICAgICAgICAgICAgICAgICBjb3JyZWxhdGlvbiA9IGNvckFSMSgpLAogICAgICAgICAgICAgICAgICBjb250cm9sID0gY3RybF9jb25maWcsCiAgICAgICAgICAgICAgICAgIG1ldGhvZCA9ICdNTCcpCgogICMgY3Jvc3MgbGV2ZWwgaW50ZXJhY3Rpb24KICBpbnRlcmFjdGlvbiA8LSBsbWUoZml4ZWQgPSB5IH4gbHZsMV94ICogbHZsMl94LCAKICAgICAgICAgICAgICAgICAgICAgcmFuZG9tID0gfiBsdmwxX3ggfCBsdmwyX2lkLCAKICAgICAgICAgICAgICAgICAgICAgICBkYXRhID0gZGF0YSwKICAgICAgICAgICAgICAgICAgICAgICBjb3JyZWxhdGlvbiA9IGNvckFSMSgpLAogICAgICAgICAgICAgICAgICBjb250cm9sID0gY3RybF9jb25maWcsCiAgICAgICAgICAgICAgICAgIG1ldGhvZCA9ICdNTCcpCiAgCiAgIyBjcmVhdGUgbGlzdCB3aXRoIHJlc3VsdHMKICByZXN1bHRzIDwtIGxpc3QoJ2Jhc2VsaW5lJyA9IGJhc2VsaW5lLCAKICAgICAgICAgICAgICAgICAgInJhbmRvbV9pbnRlcmNlcHQiID0gcmFuZG9tX2ludGVyY2VwdCwgCiAgICAgICAgICAgICAgICAgICJyYW5kb21fc2xvcGUiID0gcmFuZG9tX3Nsb3BlLAogICAgICAgICAgICAgICAgICAiaW50ZXJhY3Rpb24iID0gaW50ZXJhY3Rpb24pCiAgCiAgCiAgaWYgKGN0cmxzID09ICdkZW0nIHwgY3RybHMgPT0gJ3ByZXYnKXsKICAgIAogICAgIyByYW5kb20gaW50ZXJjZXB0IHJhbmRvbSBzbG9wZQogICAgcmFuZG9tX3Nsb3BlX2N0cmxfZGVtIDwtIGxtZShmaXhlZCA9IHkgfiBsdmwxX3ggKyBsdmwyX3ggKyBwb3BkZW5zLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICByYW5kb20gPSB+IGx2bDFfeCB8IGx2bDJfaWQsIAogICAgICAgICAgICAgICAgICAgICAgICAgIGRhdGEgPSBkYXRhLAogICAgICAgICAgICAgICAgICAgICAgICAgIGNvcnJlbGF0aW9uID0gY29yQVIxKCksCiAgICAgICAgICAgICAgICAgICAgY29udHJvbCA9IGN0cmxfY29uZmlnLAogICAgICAgICAgICAgICAgICBtZXRob2QgPSAnTUwnKQogIAogICAgIyBjcm9zcyBsZXZlbCBpbnRlcmFjdGlvbgogICAgaW50ZXJhY3Rpb25fY3RybF9tYWluX2RlbSA8LSBsbWUoZml4ZWQgPSB5IH4gbHZsMV94ICogbHZsMl94ICsgcG9wZGVucywKICAgICAgICAgICAgICAgICAgICAgICAgICAgICByYW5kb20gPSB+IGx2bDFfeCB8IGx2bDJfaWQsIAogICAgICAgICAgICAgICAgICAgICAgICAgZGF0YSA9IGRhdGEsCiAgICAgICAgICAgICAgICAgICAgICAgICBjb3JyZWxhdGlvbiA9IGNvckFSMSgpLAogICAgICAgICAgICAgICAgICAgIGNvbnRyb2wgPSBjdHJsX2NvbmZpZywKICAgICAgICAgICAgICAgICAgbWV0aG9kID0gJ01MJykKICAKICAgICMgY3Jvc3MgbGV2ZWwgaW50ZXJhY3Rpb24KICAgIGludGVyYWN0aW9uX2N0cmxfaW50X2RlbSA8LSBsbWUoZml4ZWQgPSB5IH4gbHZsMV94ICogbHZsMl94ICsgbHZsMV94ICogcG9wZGVucywKICAgICAgICAgICAgICAgICAgICAgICAgICAgICByYW5kb20gPSB+IGx2bDFfeCB8IGx2bDJfaWQsIAogICAgICAgICAgICAgICAgICAgICAgICAgZGF0YSA9IGRhdGEsCiAgICAgICAgICAgICAgICAgICAgICAgICBjb3JyZWxhdGlvbiA9IGNvckFSMSgpLAogICAgICAgICAgICAgICAgICAgIGNvbnRyb2wgPSBjdHJsX2NvbmZpZywKICAgICAgICAgICAgICAgICAgbWV0aG9kID0gJ01MJykgICAgICAgIAogICAgCiAgICAjIGNyZWF0ZSBsaXN0IHdpdGggcmVzdWx0cwogICAgcmVzdWx0cyA8LSBsaXN0KCdiYXNlbGluZScgPSBiYXNlbGluZSwgCiAgICAgICAgICAgICAgICAgICAgInJhbmRvbV9pbnRlcmNlcHQiID0gcmFuZG9tX2ludGVyY2VwdCwgCiAgICAgICAgICAgICAgICAgICAgInJhbmRvbV9zbG9wZSIgPSByYW5kb21fc2xvcGUsCiAgICAgICAgICAgICAgICAgICAgImludGVyYWN0aW9uIiA9IGludGVyYWN0aW9uLAogICAgICAgICAgICAgICAgICAgICJyYW5kb21fc2xvcGVfY3RybF9kZW0iID0gcmFuZG9tX3Nsb3BlX2N0cmxfZGVtLAogICAgICAgICAgICAgICAgICAgICJpbnRlcmFjdGlvbl9jdHJsX21haW5fZGVtIiA9IGludGVyYWN0aW9uX2N0cmxfbWFpbl9kZW0sCiAgICAgICAgICAgICAgICAgICAgImludGVyYWN0aW9uX2N0cmxfaW50X2RlbSIgPSBpbnRlcmFjdGlvbl9jdHJsX2ludF9kZW0pCiAgfQogIAogIGlmIChjdHJscyA9PSAncHJldicpewogIAogICAgIyByYW5kb20gaW50ZXJjZXB0IHJhbmRvbSBzbG9wZQogICAgcmFuZG9tX3Nsb3BlX2N0cmxfcHJldiA8LSBsbWUoZml4ZWQgPSB5IH4gbHZsMV94ICsgbHZsMl94ICsgcG9wZGVucyArIHJhdGVfZGF5LAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICByYW5kb20gPSB+IGx2bDFfeCArIHJhdGVfZGF5IHwgbHZsMl9pZCwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgZGF0YSA9IGRhdGEsCiAgICAgICAgICAgICAgICAgICAgICAgICAgY29ycmVsYXRpb24gPSBjb3JBUjEoKSwKICAgICAgICAgICAgICAgICAgICAgICAgICBjb250cm9sID0gY3RybF9jb25maWcsCiAgICAgICAgICAgICAgICAgIG1ldGhvZCA9ICdNTCcpICAKICAgIAogICAgICAgICMgY3Jvc3MgbGV2ZWwgaW50ZXJhY3Rpb24KICAgIGludGVyYWN0aW9uX2N0cmxfbWFpbl9wcmV2IDwtIGxtZShmaXhlZCA9IHkgfiBsdmwxX3ggKiBsdmwyX3ggKyBwb3BkZW5zICsgcmF0ZV9kYXksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmFuZG9tID0gfiBsdmwxX3ggfCBsdmwyX2lkLCAKICAgICAgICAgICAgICAgICAgICAgICAgIGRhdGEgPSBkYXRhLAogICAgICAgICAgICAgICAgICAgICAgICAgY29ycmVsYXRpb24gPSBjb3JBUjEoKSwKICAgICAgICAgICAgICAgICAgICBjb250cm9sID0gY3RybF9jb25maWcsCiAgICAgICAgICAgICAgICAgIG1ldGhvZCA9ICdNTCcpCiAgCiAgCiAgICAjIGNyb3NzIGxldmVsIGludGVyYWN0aW9uCiAgICBpbnRlcmFjdGlvbl9jdHJsX2ludF9wcmV2PC0gbG1lKGZpeGVkID0geSB+IGx2bDFfeCAqIGx2bDJfeCArIGx2bDFfeCAqIHBvcGRlbnMgKyByYXRlX2RheSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICByYW5kb20gPSB+IGx2bDFfeCArIHJhdGVfZGF5IHwgbHZsMl9pZCwgCiAgICAgICAgICAgICAgICAgICAgICAgICBkYXRhID0gZGF0YSwKICAgICAgICAgICAgICAgICAgICAgICAgIGNvcnJlbGF0aW9uID0gY29yQVIxKCksCiAgICAgICAgICAgICAgICAgICAgICAgICAgY29udHJvbCA9IGN0cmxfY29uZmlnLAogICAgICAgICAgICAgICAgICBtZXRob2QgPSAnTUwnKQogIAogICAgIyBjcmVhdGUgbGlzdCB3aXRoIHJlc3VsdHMKICAgIHJlc3VsdHMgPC0gbGlzdCgnYmFzZWxpbmUnID0gYmFzZWxpbmUsIAogICAgICAgICAgICAgICAgICAgICJyYW5kb21faW50ZXJjZXB0IiA9IHJhbmRvbV9pbnRlcmNlcHQsIAogICAgICAgICAgICAgICAgICAgICJyYW5kb21fc2xvcGUiID0gcmFuZG9tX3Nsb3BlLAogICAgICAgICAgICAgICAgICAgICJpbnRlcmFjdGlvbiIgPSBpbnRlcmFjdGlvbiwKICAgICAgICAgICAgICAgICAgICAicmFuZG9tX3Nsb3BlX2N0cmxfZGVtIiA9IHJhbmRvbV9zbG9wZV9jdHJsX2RlbSwKICAgICAgICAgICAgICAgICAgICAiaW50ZXJhY3Rpb25fY3RybF9tYWluX2RlbSIgPSBpbnRlcmFjdGlvbl9jdHJsX21haW5fZGVtLAogICAgICAgICAgICAgICAgICAgICJpbnRlcmFjdGlvbl9jdHJsX2ludF9kZW0iID0gaW50ZXJhY3Rpb25fY3RybF9pbnRfZGVtLCAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgInJhbmRvbV9zbG9wZV9jdHJsX3ByZXYiID0gcmFuZG9tX3Nsb3BlX2N0cmxfcHJldiwKICAgICAgICAgICAgICAgICAgICAiaW50ZXJhY3Rpb25fY3RybF9tYWluX3ByZXYiID0gaW50ZXJhY3Rpb25fY3RybF9tYWluX3ByZXYsCiAgICAgICAgICAgICAgICAgICAgImludGVyYWN0aW9uX2N0cmxfaW50X3ByZXYiID0gaW50ZXJhY3Rpb25fY3RybF9pbnRfcHJldikKICB9CiAgCiAgaWYoY3RybHMgPT0gJ2V4cCcpewogICAgIyByYW5kb20gaW50ZXJjZXB0IHJhbmRvbSBzbG9wZQogIHJhbmRvbV9zbG9wZV9leHAgPC0gbG1lKGZpeGVkID0geSB+IChsdmwxX3ggKyBJKGx2bDFfeF4yKSkgKyBsdmwyX3gsIAogICAgICAgICAgICAgICAgICAgICAgcmFuZG9tID0gfiAobHZsMV94ICsgSShsdmwxX3heMikpIHwgbHZsMl9pZCwgCiAgICAgICAgICAgICAgICAgICAgICAgIGRhdGEgPSBkYXRhLAogICAgICAgICAgICAgICAgICAgICAgICBjb3JyZWxhdGlvbiA9IGNvckFSMSgpLAogICAgICAgICAgICAgICAgICBjb250cm9sID0gY3RybF9jb25maWcsCiAgICAgICAgICAgICAgICAgIG1ldGhvZCA9ICdNTCcpCgogICMgY3Jvc3MgbGV2ZWwgaW50ZXJhY3Rpb24KICBpbnRlcmFjdGlvbl9leHAgPC0gbG1lKGZpeGVkID0geSB+IChsdmwxX3ggKyBJKGx2bDFfeF4yKSkgKiBsdmwyX3gsIAogICAgICAgICAgICAgICAgICAgICByYW5kb20gPSB+IChsdmwxX3ggKyBJKGx2bDFfeF4yKSkgfCBsdmwyX2lkLCAKICAgICAgICAgICAgICAgICAgICAgICBkYXRhID0gZGF0YSwKICAgICAgICAgICAgICAgICAgICAgICBjb3JyZWxhdGlvbiA9IGNvckFSMSgpLAogICAgICAgICAgICAgICAgICBjb250cm9sID0gY3RybF9jb25maWcsCiAgICAgICAgICAgICAgICAgIG1ldGhvZCA9ICdNTCcpICAKICAKICAKICAjIGNyZWF0ZSBsaXN0IHdpdGggcmVzdWx0cwogIHJlc3VsdHMgPC0gbGlzdCgnYmFzZWxpbmUnID0gYmFzZWxpbmUsIAogICAgICAgICAgICAgICAgICAicmFuZG9tX2ludGVyY2VwdCIgPSByYW5kb21faW50ZXJjZXB0LCAKICAgICAgICAgICAgICAgICAgInJhbmRvbV9zbG9wZSIgPSByYW5kb21fc2xvcGUsCiAgICAgICAgICAgICAgICAgICJpbnRlcmFjdGlvbiIgPSBpbnRlcmFjdGlvbiwgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgInJhbmRvbV9zbG9wZV9leHAiID0gcmFuZG9tX3Nsb3BlX2V4cCwKICAgICAgICAgICAgICAgICAgImludGVyYWN0aW9uX2V4cCIgPSBpbnRlcmFjdGlvbl9leHApCiAgfQogIAogIHJldHVybihyZXN1bHRzKQogICAgICAgIAp9CgojIGV4dHJhY3RzIHRhYmxlIHdpdGggY29lZmZpY2llbnRzIGFuZCB0ZXN0cyBzdGF0aXN0aWNzCmV4dHJhY3RfcmVzdWx0cyA8LSBmdW5jdGlvbihtb2RlbHMpIHsKICAKICBtb2RlbHNfc3VtbWFyeSA8LSBtb2RlbHMgJT4lIAogIG1hcChzdW1tYXJ5KSAlPiUgCiAgbWFwKCJ0VGFibGUiKSAlPiUgCiAgbWFwKGFzLmRhdGEuZnJhbWUpICU+JSAKICBtYXAocm91bmQsIDEwKSAKICAjICU+JSBtYXAofiAuW3N0cl9kZXRlY3Qocm93bmFtZXMoLiksICdJbnRlcnxsdmwnKSxdKQogIAogIHJldHVybihtb2RlbHNfc3VtbWFyeSkKICAKfQoKCiMgY2FsY3VsYXRlcyBjb21wYXJpc29uIG9mIGFsbCBtb2RlbHMgaW4gbW9kZWwgbGlzdApjb21wYXJlX21vZGVscyA8LSBmdW5jdGlvbihtb2RlbHMpIHsKCiAgbWRsX25hbWVzIDwtIG1vZGVscyAlPiUgbmFtZXMoKQogIAogIHN0ciA9ICcnCiAgZm9yIChpIGluIG1kbF9uYW1lcyl7CiAgICAKICAgIG1kbF9zdHIgPC0gcGFzdGUoJ21vZGVscyQnLCBpLCBzZXAgPSAnJykKICAgIAogICAgaWYoaSA9PSAnYmFzZWxpbmUnKXsKICAgICAgc3RyIDwtIG1kbF9zdHIKICAgIH1lbHNlewogICAgc3RyIDwtIHBhc3RlKHN0ciwgbWRsX3N0ciwgc2VwPScsICcpCiAgICB9CiAgfQogIAogIGFub3ZhX3N0ciA8LSBwYXN0ZTAoJ2Fub3ZhKCcsIHN0ciwgJyknKQogIG1kbF9jb21wIDwtIGV2YWwocGFyc2UodGV4dD1hbm92YV9zdHIpKQogIHJvd25hbWVzKG1kbF9jb21wKSA9IG1kbF9uYW1lcwogIHJldHVybihtZGxfY29tcCkKfQoKCmBgYAoKIyMgUmVtb3ZlIExvbmRvbiBEYXRhIApgYGB7cn0KIyBkZl91ayA8LSBkZl91ayAlPiUgZmlsdGVyKGxvbmRvbiA9PSAnY291bnRyeScpCiMgZGZfdWtfc29jZGlzdCA8LSBkZl91a19zb2NkaXN0ICU+JSBmaWx0ZXIobG9uZG9uID09ICdjb3VudHJ5JykKCmBgYAoKCgojIyBSZXNjYWxlIERhdGEKYGBge3J9Cmx2bDJfc2NhbGVkX3V0IDwtIGRmX3VrICU+JSAKICBkcGx5cjo6c2VsZWN0KC10aW1lLCAtZGF0ZSwgLXJhdGVfZGF5LCAtbG9uZG9uKSAlPiUgCiAgZGlzdGluY3QoKSAlPiUgCiAgbXV0YXRlX2F0KHZhcnMoLXV0X2FyZWEpLCBzY2FsZSkKCmx2bDFfc2NhbGVkX3V0IDwtIGRmX3VrICU+JSBzZWxlY3QodXRfYXJlYSwgdGltZSwgcmF0ZV9kYXkpICU+JSAKICBtdXRhdGVfYXQodmFycygtdXRfYXJlYSwgLXRpbWUpLCBzY2FsZSkKCmRmX3VrX3NjYWxlZCA8LSBwbHlyOjpqb2luKGx2bDFfc2NhbGVkX3V0LCBsdmwyX3NjYWxlZF91dCwgYnkgPSAndXRfYXJlYScpCgpkZl91a19zY2FsZWQKYGBgCgoKYGBge3J9CgpsdmwyX3NjYWxlZF9udXRzIDwtIGRmX3VrX3NvY2Rpc3QgJT4lIAogIGRwbHlyOjpzZWxlY3QoLXRpbWUsIC1kYXRlLCAtbG9uZG9uLCAKICAgICAgICAgICAgICAgIC1zb2NkaXN0X3RpbGVzLCAtc29jZGlzdF9zaW5nbGVfdGlsZSwgLXJhdGVfZGF5KSAlPiUgCiAgZGlzdGluY3QoKSAlPiUgCiAgbXV0YXRlX2F0KHZhcnMoLW51dHMzKSwgc2NhbGUpCgpsdmwxX3NjYWxlZF9udXRzIDwtIGRmX3VrX3NvY2Rpc3QgJT4lIHNlbGVjdChudXRzMywgdGltZSwgc29jZGlzdF9zaW5nbGVfdGlsZSwgcmF0ZV9kYXkpICU+JSAKICBtdXRhdGVfYXQodmFycygtbnV0czMsIC10aW1lKSwgc2NhbGUpCgpkZl91a19zb2NkaXN0X3NjYWxlZCA8LSBwbHlyOjpqb2luKGx2bDFfc2NhbGVkX251dHMsIGx2bDJfc2NhbGVkX251dHMsIGJ5ID0gJ251dHMzJykKCmRmX3VrX3NvY2Rpc3Rfc2NhbGVkCgpgYGAKCiMjIyBBZGp1c3QgdGltZWZyYW1lcyAKYGBge3J9CgpkZl91a19zY2FsZWRfcHJldiA8LSBkZl91a19zY2FsZWQgJT4lIGZpbHRlcih0aW1lID4gNDAgJiB0aW1lIDw9IDcwKQoKYGBgCgoKCgojIyBQcmVkaWN0IHByZXZhbGVuY2UKIyMjIHByZXZhbGVuY2UgfiBvcGVubmVzcwpgYGB7cn0KCm1vZGVsc19vX2NvdmlkIDwtcnVuX21vZGVscyh5ID0gJ3JhdGVfZGF5JywgCiAgICAgICAgICAgICAgICAgICAgICAgICBsdmwxX3ggPSAndGltZScsIAogICAgICAgICAgICAgICAgICAgICAgICAgbHZsMl94ID0gJ3BlcnNfbycsIAogICAgICAgICAgICAgICAgICAgICAgICAgbHZsMl9pZCA9ICd1dF9hcmVhJywgCiAgICAgICAgICAgICAgICAgICAgICAgICBkYXRhID0gZGZfdWtfc2NhbGVkX3ByZXYsCiAgICAgICAgICAgICAgICAgICAgICAgICBjdHJscyA9ICdkZW0nKQoKZXh0cmFjdF9yZXN1bHRzKG1vZGVsc19vX2NvdmlkKQoKY29tcGFyZV9tb2RlbHMobW9kZWxzX29fY292aWQpCgpgYGAKCiMjIyBwcmV2YWxlbmNlIH4gY29uc2NpZW50aW91c25lc3MKYGBge3J9Cgptb2RlbHNfY19jb3ZpZCA8LXJ1bl9tb2RlbHMoeSA9ICdyYXRlX2RheScsIAogICAgICAgICAgICAgICAgICAgICAgICAgbHZsMV94ID0gJ3RpbWUnLCAKICAgICAgICAgICAgICAgICAgICAgICAgIGx2bDJfeCA9ICdwZXJzX2MnLCAKICAgICAgICAgICAgICAgICAgICAgICAgIGx2bDJfaWQgPSAndXRfYXJlYScsIAogICAgICAgICAgICAgICAgICAgICAgICAgZGF0YSA9IGRmX3VrX3NjYWxlZF9wcmV2LAogICAgICAgICAgICAgICAgICAgICAgICAgY3RybHMgPSAnZGVtJykKCmV4dHJhY3RfcmVzdWx0cyhtb2RlbHNfY19jb3ZpZCkKCmNvbXBhcmVfbW9kZWxzKG1vZGVsc19jX2NvdmlkKQoKCmBgYAoKIyMjIHByZXZhbGVuY2UgfiBleHRyYXZlcnNpb24KYGBge3J9Cgptb2RlbHNfZV9jb3ZpZCA8LXJ1bl9tb2RlbHMoeSA9ICdyYXRlX2RheScsIAogICAgICAgICAgICAgICAgICAgICAgICAgbHZsMV94ID0gJ3RpbWUnLCAKICAgICAgICAgICAgICAgICAgICAgICAgIGx2bDJfeCA9ICdwZXJzX2UnLCAKICAgICAgICAgICAgICAgICAgICAgICAgIGx2bDJfaWQgPSAndXRfYXJlYScsIAogICAgICAgICAgICAgICAgICAgICAgICAgZGF0YSA9IGRmX3VrX3NjYWxlZF9wcmV2LAogICAgICAgICAgICAgICAgICAgICAgICAgY3RybHMgPSAnZGVtJykKCmV4dHJhY3RfcmVzdWx0cyhtb2RlbHNfZV9jb3ZpZCkKCmNvbXBhcmVfbW9kZWxzKG1vZGVsc19lX2NvdmlkKQoKCmBgYAoKIyMjIHByZXZhbGVuY2UgfiBhZ3JlZWFibGVuZXNzCmBgYHtyfQoKbW9kZWxzX2FfY292aWQgPC1ydW5fbW9kZWxzKHkgPSAncmF0ZV9kYXknLCAKICAgICAgICAgICAgICAgICAgICAgICAgIGx2bDFfeCA9ICd0aW1lJywgCiAgICAgICAgICAgICAgICAgICAgICAgICBsdmwyX3ggPSAncGVyc19hJywgCiAgICAgICAgICAgICAgICAgICAgICAgICBsdmwyX2lkID0gJ3V0X2FyZWEnLCAKICAgICAgICAgICAgICAgICAgICAgICAgIGRhdGEgPSBkZl91a19zY2FsZWRfcHJldiwKICAgICAgICAgICAgICAgICAgICAgICAgIGN0cmxzID0gJ2RlbScpCgpleHRyYWN0X3Jlc3VsdHMobW9kZWxzX2FfY292aWQpCgpjb21wYXJlX21vZGVscyhtb2RlbHNfYV9jb3ZpZCkKCgpgYGAKCiMjIyBwcmV2YWxlbmNlIH4gbmV1cm90aWNpc20KYGBge3J9Cgptb2RlbHNfbl9jb3ZpZCA8LXJ1bl9tb2RlbHMoeSA9ICdyYXRlX2RheScsIAogICAgICAgICAgICAgICAgICAgICAgICAgbHZsMV94ID0gJ3RpbWUnLCAKICAgICAgICAgICAgICAgICAgICAgICAgIGx2bDJfeCA9ICdwZXJzX24nLCAKICAgICAgICAgICAgICAgICAgICAgICAgIGx2bDJfaWQgPSAndXRfYXJlYScsIAogICAgICAgICAgICAgICAgICAgICAgICAgZGF0YSA9IGRmX3VrX3NjYWxlZF9wcmV2LAogICAgICAgICAgICAgICAgICAgICAgICAgY3RybHMgPSAnZGVtJykKCmV4dHJhY3RfcmVzdWx0cyhtb2RlbHNfbl9jb3ZpZCkKCmNvbXBhcmVfbW9kZWxzKG1vZGVsc19uX2NvdmlkKQoKCmBgYAoKCiMjIFByZWRpY3Qgc29jaWFsIGRpc3RhbmNpbmcKIyMjIHNvY2lhbCBkaXN0YW5jaW5nIH4gb3Blbm5lc3MKYGBge3J9Cgptb2RlbHNfb19zb2NkaXN0IDwtcnVuX21vZGVscyh5ID0gJ3NvY2Rpc3Rfc2luZ2xlX3RpbGUnLCAKICAgICAgICAgICAgICAgICAgICAgICAgIGx2bDFfeCA9ICd0aW1lJywgCiAgICAgICAgICAgICAgICAgICAgICAgICBsdmwyX3ggPSAncGVyc19vJywgCiAgICAgICAgICAgICAgICAgICAgICAgICBsdmwyX2lkID0gJ251dHMzJywgCiAgICAgICAgICAgICAgICAgICAgICAgICBkYXRhID0gZGZfdWtfc29jZGlzdF9zY2FsZWQsCiAgICAgICAgICAgICAgICAgICAgICAgICBjdHJscyA9ICdwcmV2JykKCmV4dHJhY3RfcmVzdWx0cyhtb2RlbHNfb19zb2NkaXN0KQoKY29tcGFyZV9tb2RlbHMobW9kZWxzX29fc29jZGlzdCkKCmBgYAoKIyMjIHNvY2lhbCBkaXN0YW5jaW5nIH4gY29uc2NpZW50aW91c25lc3MKYGBge3J9Cgptb2RlbHNfY19zb2NkaXN0IDwtcnVuX21vZGVscyh5ID0gJ3NvY2Rpc3Rfc2luZ2xlX3RpbGUnLCAKICAgICAgICAgICAgICAgICAgICAgICAgIGx2bDFfeCA9ICd0aW1lJywgCiAgICAgICAgICAgICAgICAgICAgICAgICBsdmwyX3ggPSAncGVyc19jJywgCiAgICAgICAgICAgICAgICAgICAgICAgICBsdmwyX2lkID0gJ251dHMzJywgCiAgICAgICAgICAgICAgICAgICAgICAgICBkYXRhID0gZGZfdWtfc29jZGlzdF9zY2FsZWQsCiAgICAgICAgICAgICAgICAgICAgICAgICBjdHJscyA9ICdwcmV2JykKCmV4dHJhY3RfcmVzdWx0cyhtb2RlbHNfY19zb2NkaXN0KQoKY29tcGFyZV9tb2RlbHMobW9kZWxzX2Nfc29jZGlzdCkKCgpgYGAKCiMjIyBzb2NpYWwgZGlzdGFuY2luZyB+IGV4dHJhdmVyc2lvbgpgYGB7cn0KCm1vZGVsc19lX3NvY2Rpc3QgPC1ydW5fbW9kZWxzKHkgPSAnc29jZGlzdF9zaW5nbGVfdGlsZScsIAogICAgICAgICAgICAgICAgICAgICAgICAgbHZsMV94ID0gJ3RpbWUnLCAKICAgICAgICAgICAgICAgICAgICAgICAgIGx2bDJfeCA9ICdwZXJzX2UnLCAKICAgICAgICAgICAgICAgICAgICAgICAgIGx2bDJfaWQgPSAnbnV0czMnLCAKICAgICAgICAgICAgICAgICAgICAgICAgIGRhdGEgPSBkZl91a19zb2NkaXN0X3NjYWxlZCwKICAgICAgICAgICAgICAgICAgICAgICAgIGN0cmxzID0gJ3ByZXYnKQoKZXh0cmFjdF9yZXN1bHRzKG1vZGVsc19lX3NvY2Rpc3QpCgpjb21wYXJlX21vZGVscyhtb2RlbHNfZV9zb2NkaXN0KQoKCmBgYAoKIyMjIHNvY2lhbCBkaXN0YW5jaW5nIH4gYWdyZWVhYmxlbmVzcwpgYGB7cn0KCm1vZGVsc19hX3NvY2Rpc3QgPC1ydW5fbW9kZWxzKHkgPSAnc29jZGlzdF9zaW5nbGVfdGlsZScsIAogICAgICAgICAgICAgICAgICAgICAgICAgbHZsMV94ID0gJ3RpbWUnLCAKICAgICAgICAgICAgICAgICAgICAgICAgIGx2bDJfeCA9ICdwZXJzX2EnLCAKICAgICAgICAgICAgICAgICAgICAgICAgIGx2bDJfaWQgPSAnbnV0czMnLCAKICAgICAgICAgICAgICAgICAgICAgICAgIGRhdGEgPSBkZl91a19zb2NkaXN0X3NjYWxlZCwKICAgICAgICAgICAgICAgICAgICAgICAgIGN0cmxzID0gJ3ByZXYnKQoKZXh0cmFjdF9yZXN1bHRzKG1vZGVsc19hX3NvY2Rpc3QpCgpjb21wYXJlX21vZGVscyhtb2RlbHNfYV9zb2NkaXN0KQoKCmBgYAoKIyMjIHNvY2lhbCBkaXN0YW5jaW5nIH4gbmV1cm90aWNpc20KYGBge3J9Cgptb2RlbHNfbl9zb2NkaXN0IDwtcnVuX21vZGVscyh5ID0gJ3NvY2Rpc3Rfc2luZ2xlX3RpbGUnLCAKICAgICAgICAgICAgICAgICAgICAgICAgIGx2bDFfeCA9ICd0aW1lJywgCiAgICAgICAgICAgICAgICAgICAgICAgICBsdmwyX3ggPSAncGVyc19uJywgCiAgICAgICAgICAgICAgICAgICAgICAgICBsdmwyX2lkID0gJ251dHMzJywgCiAgICAgICAgICAgICAgICAgICAgICAgICBkYXRhID0gZGZfdWtfc29jZGlzdF9zY2FsZWQsCiAgICAgICAgICAgICAgICAgICAgICAgICBjdHJscyA9ICdwcmV2JykKCmV4dHJhY3RfcmVzdWx0cyhtb2RlbHNfbl9zb2NkaXN0KQoKY29tcGFyZV9tb2RlbHMobW9kZWxzX25fc29jZGlzdCkKCgpgYGAKCgojIyBFeHBsb3JlIHF1YWRyYXRpYyB0cmVuZHMgCgojIyMgcHJldmFsZW5jZSB+IG9wZW5uZXNzCmBgYHtyfQoKbW9kZWxzX29fY292aWRfZXhwIDwtcnVuX21vZGVscyh5ID0gJ3JhdGVfZGF5JywKICAgICAgICAgICAgICAgICAgICAgICAgIGx2bDFfeCA9ICd0aW1lJywKICAgICAgICAgICAgICAgICAgICAgICAgIGx2bDJfeCA9ICdwZXJzX28nLAogICAgICAgICAgICAgICAgICAgICAgICAgbHZsMl9pZCA9ICd1dF9hcmVhJywKICAgICAgICAgICAgICAgICAgICAgICAgIGRhdGEgPSBkZl91a19zY2FsZWRfcHJldiwKICAgICAgICAgICAgICAgICAgICAgICAgIGN0cmxzID0gJ2V4cCcpCgpleHRyYWN0X3Jlc3VsdHMobW9kZWxzX29fY292aWRfZXhwKQoKY29tcGFyZV9tb2RlbHMobW9kZWxzX29fY292aWRfZXhwKQoKYGBgCgoKIyMgcHJldmFsZW5jZSB+IGNvbnNjaWVudGlvdXNuZXNzCmBgYHtyfQoKbW9kZWxzX2NfY292aWRfZXhwIDwtcnVuX21vZGVscyh5ID0gJ3JhdGVfZGF5JywgCiAgICAgICAgICAgICAgICAgICAgICAgICBsdmwxX3ggPSAndGltZScsIAogICAgICAgICAgICAgICAgICAgICAgICAgbHZsMl94ID0gJ3BlcnNfYycsIAogICAgICAgICAgICAgICAgICAgICAgICAgbHZsMl9pZCA9ICd1dF9hcmVhJywgCiAgICAgICAgICAgICAgICAgICAgICAgICBkYXRhID0gZGZfdWtfc2NhbGVkX3ByZXYsCiAgICAgICAgICAgICAgICAgICAgICAgICBjdHJscyA9ICdleHAnKQoKZXh0cmFjdF9yZXN1bHRzKG1vZGVsc19jX2NvdmlkX2V4cCkKCmNvbXBhcmVfbW9kZWxzKG1vZGVsc19jX2NvdmlkX2V4cCkKCmBgYAoKIyMjIHByZXZhbGVuY2UgfiBleHRyYXZlcnNpb24KYGBge3J9Cgptb2RlbHNfZV9jb3ZpZF9leHAgPC1ydW5fbW9kZWxzKHkgPSAncmF0ZV9kYXknLCAKICAgICAgICAgICAgICAgICAgICAgICAgIGx2bDFfeCA9ICd0aW1lJywgCiAgICAgICAgICAgICAgICAgICAgICAgICBsdmwyX3ggPSAncGVyc19lJywgCiAgICAgICAgICAgICAgICAgICAgICAgICBsdmwyX2lkID0gJ3V0X2FyZWEnLCAKICAgICAgICAgICAgICAgICAgICAgICAgIGRhdGEgPSBkZl91a19zY2FsZWRfcHJldiwKICAgICAgICAgICAgICAgICAgICAgICAgIGN0cmxzID0gJ2V4cCcpCgpleHRyYWN0X3Jlc3VsdHMobW9kZWxzX2VfY292aWRfZXhwKQoKY29tcGFyZV9tb2RlbHMobW9kZWxzX2VfY292aWRfZXhwKQoKYGBgCgojIyMgcHJldmFsZW5jZSB+IGFncmVlYWJsZW5lc3MKYGBge3J9Cgptb2RlbHNfYV9jb3ZpZF9leHAgPC1ydW5fbW9kZWxzKHkgPSAncmF0ZV9kYXknLCAKICAgICAgICAgICAgICAgICAgICAgICAgIGx2bDFfeCA9ICd0aW1lJywgCiAgICAgICAgICAgICAgICAgICAgICAgICBsdmwyX3ggPSAncGVyc19hJywgCiAgICAgICAgICAgICAgICAgICAgICAgICBsdmwyX2lkID0gJ3V0X2FyZWEnLCAKICAgICAgICAgICAgICAgICAgICAgICAgIGRhdGEgPSBkZl91a19zY2FsZWRfcHJldiwKICAgICAgICAgICAgICAgICAgICAgICAgIGN0cmxzID0gJ2V4cCcpCgpleHRyYWN0X3Jlc3VsdHMobW9kZWxzX2FfY292aWRfZXhwKQoKY29tcGFyZV9tb2RlbHMobW9kZWxzX2FfY292aWRfZXhwKQoKYGBgCgojIyMgcHJldmFsZW5jZSB+IG5ldXJvdGljaXNtCmBgYHtyfQoKbW9kZWxzX25fY292aWRfZXhwIDwtcnVuX21vZGVscyh5ID0gJ3JhdGVfZGF5JywgCiAgICAgICAgICAgICAgICAgICAgICAgICBsdmwxX3ggPSAndGltZScsIAogICAgICAgICAgICAgICAgICAgICAgICAgbHZsMl94ID0gJ3BlcnNfbicsIAogICAgICAgICAgICAgICAgICAgICAgICAgbHZsMl9pZCA9ICd1dF9hcmVhJywgCiAgICAgICAgICAgICAgICAgICAgICAgICBkYXRhID0gZGZfdWtfc2NhbGVkX3ByZXYsCiAgICAgICAgICAgICAgICAgICAgICAgICBjdHJscyA9ICdleHAnKQoKZXh0cmFjdF9yZXN1bHRzKG1vZGVsc19uX2NvdmlkX2V4cCkKCmNvbXBhcmVfbW9kZWxzKG1vZGVsc19uX2NvdmlkX2V4cCkKCmBgYAoKIyMgQ3JlYXRlIG92ZXJ2aWV3IHRhYmxlIAoKIyMjIERlZmluZSBmdW5jdGlvbiB0byBjcmVhdGUgb3ZlcnZpZXcgdGFibGVzCmBgYHtyfQoKc3VtbWFyeV90YWJsZSA8LSBmdW5jdGlvbihtb2RlbHMsIGR2X25hbWUsIHByZXY9Ril7CgogIHRlbXBfZGZfY3RybF9tYWluIDwtIE5VTEwKICB0ZW1wX2RmX2N0cmxfaW50IDwtIE5VTEwKICB0ZW1wX2RmX2N0cmxfaW50X3ByZXYgPC0gTlVMTAogIAogIGZvciAoaSBpbiBtb2RlbHMpewogICAgcmVzdWx0cyA8LSBpICU+JSBleHRyYWN0X3Jlc3VsdHMoKQogICAgCiAgICByZXN1bHRzX2N0cmxfbWFpbiA8LSByZXN1bHRzJGludGVyYWN0aW9uX2N0cmxfbWFpbl9kZW1bJ2x2bDFfeDpsdmwyX3gnLF0KICAgIHRlbXBfZGZfY3RybF9tYWluIDwtIHRlbXBfZGZfY3RybF9tYWluICU+JSByYmluZChyZXN1bHRzX2N0cmxfbWFpbikKICAgIAogICAgcmVzdWx0c19jdHJsX2ludCA8LSByZXN1bHRzJGludGVyYWN0aW9uX2N0cmxfaW50X2RlbVsnbHZsMV94Omx2bDJfeCcsXQogICAgdGVtcF9kZl9jdHJsX2ludCA8LSB0ZW1wX2RmX2N0cmxfaW50ICU+JSByYmluZChyZXN1bHRzX2N0cmxfaW50KQogICAgCiAgICBpZihwcmV2KXsKICAgICAgcmVzdWx0c19jdHJsX2ludF9wcmV2IDwtIHJlc3VsdHMkaW50ZXJhY3Rpb25fY3RybF9pbnRfcHJldlsnbHZsMV94Omx2bDJfeCcsXQogICAgICB0ZW1wX2RmX2N0cmxfaW50X3ByZXYgPC0gdGVtcF9kZl9jdHJsX2ludF9wcmV2ICU+JSByYmluZChyZXN1bHRzX2N0cmxfaW50X3ByZXYpCiAgICB9CiAgICAgICAgCiAgfQogIAogIG5hbWVzX2N0cmxfbWFpbiA8LSBwYXN0ZTAoZHZfbmFtZSwgJ34nLCBjKCdvJywgJ2MnLCAnZScsICdhJywgJ24nKSwgJyp0aW1lJywgJ19jcnRsX3BvcGRlbnMnKQogIHJvd25hbWVzKHRlbXBfZGZfY3RybF9tYWluKSA8LSBuYW1lc19jdHJsX21haW4KCiAgbmFtZXNfY3RybF9pbnQgPC0gcGFzdGUwKGR2X25hbWUsICd+JywgYygnbycsICdjJywgJ2UnLCAnYScsICduJyksICcqdGltZScsICdfY3J0bF9wb3BkZW5zKnRpbWUnKQogIHJvd25hbWVzKHRlbXBfZGZfY3RybF9pbnQpIDwtIG5hbWVzX2N0cmxfaW50CgogIGlmKHByZXYpewogICAgbmFtZXNfY3RybF9pbnRfcHJldiA8LSBwYXN0ZTAoZHZfbmFtZSwgJ34nLCBjKCdvJywgJ2MnLCAnZScsICdhJywgJ24nKSwgJyp0aW1lJywgJ19jcnRsX3BvcGRlbnMqdGltZV9wcmV2JykKICAgIHJvd25hbWVzKHRlbXBfZGZfY3RybF9pbnRfcHJldikgPC0gbmFtZXNfY3RybF9pbnRfcHJldgogICAgCiAgICBzdW1fdGFiIDwtIHJiaW5kKHRlbXBfZGZfY3RybF9tYWluLCB0ZW1wX2RmX2N0cmxfaW50LCB0ZW1wX2RmX2N0cmxfaW50X3ByZXYpICU+JSByb3VuZCg0KQogIH1lbHNlewogICAgc3VtX3RhYiA8LSByYmluZCh0ZW1wX2RmX2N0cmxfbWFpbiwgdGVtcF9kZl9jdHJsX2ludCkgJT4lIHJvdW5kKDQpCiAgfQoKCiAgCiAgcmV0dXJuKHN1bV90YWIpCgp9IAoKYGBgCgojIyMgQ3JlYXRlIG92ZXJ2aWV3IHRhYmxlcwpgYGB7cn0KIyBwcmV2YWxlbmNlCm1vZGVsc19wcmV2IDwtIGxpc3QobW9kZWxzX29fY292aWQsIAogICAgICAgICAgICAgICAgICAgIG1vZGVsc19jX2NvdmlkLCAKICAgICAgICAgICAgICAgICAgICBtb2RlbHNfZV9jb3ZpZCwgCiAgICAgICAgICAgICAgICAgICAgbW9kZWxzX2FfY292aWQsIAogICAgICAgICAgICAgICAgICAgIG1vZGVsc19uX2NvdmlkKQoKc3VtX3RhYl9wcmV2IDwtIHN1bW1hcnlfdGFibGUobW9kZWxzX3ByZXYsIGR2X25hbWUgPSAncHJldicpCgp3cml0ZS50YWJsZShzdW1fdGFiX3ByZXYsIHF1b3RlPUYpCgojIHNvY2lhbCBkaXN0YW5jaW5nCm1vZGVsc19zb2NkaXN0IDwtIGxpc3QobW9kZWxzX29fc29jZGlzdCwgCiAgICAgICAgICAgICAgICAgICAgICAgbW9kZWxzX2Nfc29jZGlzdCwgCiAgICAgICAgICAgICAgICAgICAgICAgbW9kZWxzX2Vfc29jZGlzdCwgCiAgICAgICAgICAgICAgICAgICAgICAgbW9kZWxzX2Ffc29jZGlzdCwgCiAgICAgICAgICAgICAgICAgICAgICAgbW9kZWxzX25fc29jZGlzdCkKCnN1bV90YWJfc29jZGlzdCA8LSBzdW1tYXJ5X3RhYmxlKG1vZGVsc19zb2NkaXN0LCBkdl9uYW1lID0gJ3NvY2Rpc3QnLCBwcmV2PVQpCgp3cml0ZS50YWJsZShzdW1fdGFiX3NvY2Rpc3QsIHF1b3RlPUYpCgoKCmBgYAoKCgojIENvbmRpdGlvbmFsIHJhbmRvbSBmb3Jlc3QgYW5hbHlzaXMgCgojIyMgRXh0cmFjdCBzbG9wZXMgcHJldmFsZW5jZQpgYGB7cn0KCiMgc2xvcGUgcHJldmFsZW5jZQpkZl91a19zbG9wZV9wcmV2IDwtIGRmX3VrX3NjYWxlZF9wcmV2ICU+JSBzcGxpdCguJHV0X2FyZWEpICU+JSAKICBtYXAofiBsbShyYXRlX2RheSB+IHRpbWUsIGRhdGEgPSAuKSkgJT4lCiAgbWFwKGNvZWYpICU+JSAKICBtYXBfZGJsKCd0aW1lJykgJT4lIAogIGFzLmRhdGEuZnJhbWUoKSAlPiUgCiAgcm93bmFtZXNfdG9fY29sdW1uKCd1dF9hcmVhJykgJT4lIAogIHJlbmFtZShzbG9wZV9wcmV2ID0gJy4nKQoKIyBtZXJnZSB3aXRoIGNvbnRyb2wgdmFyaWFibGVzIApkZl91a19zbG9wZV9wcmV2IDwtIGRmX3VrX3NjYWxlZF9wcmV2ICU+JSBzZWxlY3QoLXRpbWUsIC1yYXRlX2RheSkgJT4lCiAgZGlzdGluY3QoKSAlPiUgCiAgaW5uZXJfam9pbihkZl91a19zbG9wZV9wcmV2LCBieSA9ICd1dF9hcmVhJykgJT4lCiAgZHJvcF9uYSgpCgpoZWFkKGRmX3VrX3Nsb3BlX3ByZXYpCgpgYGAKCgojIyMgRXh0cmFjdCBzbG9wZXMgc29jaWFsIGRpc3RhbmNpbmcKYGBge3J9CgojIHNsb3BlIHNvY2Rpc3QKZGZfdWtfc2xvcGVfc29jZGlzdCA8LSBkZl91a19zb2NkaXN0X3NjYWxlZCAlPiUgc3BsaXQoLiRudXRzMykgJT4lCiAgbWFwKH4gbG0oc29jZGlzdF9zaW5nbGVfdGlsZSB+IHRpbWUsIGRhdGEgPSAuKSkgJT4lCiAgbWFwKGNvZWYpICU+JQogIG1hcF9kYmwoJ3RpbWUnKSAlPiUKICBhcy5kYXRhLmZyYW1lKCkgJT4lCiAgcm93bmFtZXNfdG9fY29sdW1uKCdudXRzMycpICU+JQogIHJlbmFtZShzbG9wZV9zb2NkaXN0ID0gJy4nKQoKIyBtZXJnZSB3aXRoIGNvbnRyb2wgdmFyaWFibGVzIApkZl91a19zbG9wZV9zb2NkaXN0IDwtIGRmX3VrX3NvY2Rpc3Rfc2NhbGVkICU+JSAKICBzZWxlY3QoLXRpbWUsIC1kYXRlLCAtc29jZGlzdF90aWxlcywgLXNvY2Rpc3Rfc2luZ2xlX3RpbGUpICU+JQogIGRpc3RpbmN0KCkgJT4lCiAgaW5uZXJfam9pbihkZl91a19zbG9wZV9zb2NkaXN0LCBieSA9ICdudXRzMycpICU+JQogIGRyb3BfbmEoKQoKaGVhZChkZl91a19zbG9wZV9zb2NkaXN0KQoKYGBgCgojIyMgRXhwbG9yZSBkaXN0cmlidXRpb24gb2Ygc2xvcGVzCmBgYHtyfQpkZl91a19zbG9wZV9wcmV2ICU+JSBnZ3Bsb3QoYWVzKHNsb3BlX3ByZXYpKSArIGdlb21faGlzdG9ncmFtKGJpbnMgPSAxMDApCgpkZl91a19zbG9wZV9zb2NkaXN0ICU+JSBnZ3Bsb3QoYWVzKHNsb3BlX3NvY2Rpc3QpKSArIGdlb21faGlzdG9ncmFtKGJpbnMgPSAxMDApCgpgYGAKCmBgYHtyfQpkZl91a19zbG9wZV9wcmV2CmBgYAoKCiMgQ1JGIHByZXZhbGVuY2UgfiBvcGVubmVzcwpgYGB7cn0KCmN0cmxzIDwtIGNmb3Jlc3RfdW5iaWFzZWQobnRyZWU9NTAwLCBtdHJ5PTUpCgpjcmZfb19maXRfcHJldiA8LSBjZm9yZXN0KHNsb3BlX3ByZXYgfiBwZXJzX28gKyBhaXJwb3J0X2Rpc3QgKyBtYWxlcyArCiAgICAgICAgICAgICAgICAgICAgICAgICAgcG9wZGVucyArIG1hbnVmYWN0dXJpbmcgKyB0b3VyaXNtICsKICAgICAgICAgICAgICAgICAgICAgICAgICBoZWFsdGggKyBhY2FkZW1pYyArIG1lZGluYyArIG1lZGFnZSArIGNvbnNlcnZhdGl2ZSwgCiAgICAgICAgICAgICAgICAgICAgICAgICBkZl91a19zbG9wZV9wcmV2Wy0xXSwgCiAgICAgICAgICAgICAgICAgICAgICAgICBjb250cm9scyA9IGN0cmxzKQoKY3JmX29fdmFyaW1wX3ByZXYgPC0gdmFyaW1wKGNyZl9vX2ZpdF9wcmV2LCBucGVybSA9IDEpCmNyZl9vX3ZhcmltcF9jb25kX3ByZXYgPC0gdmFyaW1wKGNyZl9vX2ZpdF9wcmV2LCBjb25kaXRpb25hbCA9IFQsIG5wZXJtID0gMSkKCmNyZl9vX3ZhcmltcF9wcmV2ICU+JSBhcy5kYXRhLmZyYW1lKCkgJT4lIHJvd25hbWVzX3RvX2NvbHVtbigndmFyaWFibGUnKSAlPiUKICBnZ3Bsb3QoYWVzKHg9dmFyaWFibGUsIHk9LikpICsKICBnZW9tX2JhcihzdGF0ID0gJ2lkZW50aXR5JykgKyAKICB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDkwKSkKCmNyZl9vX3ZhcmltcF9jb25kX3ByZXYgJT4lIGFzLmRhdGEuZnJhbWUoKSAlPiUgcm93bmFtZXNfdG9fY29sdW1uKCd2YXJpYWJsZScpICU+JQogIGdncGxvdChhZXMoeD12YXJpYWJsZSwgeT0uKSkgKwogIGdlb21fYmFyKHN0YXQgPSAnaWRlbnRpdHknKSArCiAgdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSA5MCkpCgpgYGAKCiMgQ1JGIHByZXZhbGVuY2UgfiBjb25zY2llbnRpb3VzbmVzcwpgYGB7cn0KCmN0cmxzIDwtIGNmb3Jlc3RfdW5iaWFzZWQobnRyZWU9NTAwLCBtdHJ5PTUpCgpjcmZfY19maXRfcHJldiA8LSBjZm9yZXN0KHNsb3BlX3ByZXYgfiBwZXJzX2MgKyBhaXJwb3J0X2Rpc3QgKyBtYWxlcyArCiAgICAgICAgICAgICAgICAgICAgICAgICAgcG9wZGVucyArIG1hbnVmYWN0dXJpbmcgKyB0b3VyaXNtICsKICAgICAgICAgICAgICAgICAgICAgICAgICBoZWFsdGggKyBhY2FkZW1pYyArIG1lZGluYyArIG1lZGFnZSArIGNvbnNlcnZhdGl2ZSwgCiAgICAgICAgICAgICAgICAgICAgICAgICBkZl91a19zbG9wZV9wcmV2Wy0xXSwgCiAgICAgICAgICAgICAgICAgICAgICAgICBjb250cm9scyA9IGN0cmxzKQoKY3JmX2NfdmFyaW1wX3ByZXYgPC0gdmFyaW1wKGNyZl9jX2ZpdF9wcmV2LCBucGVybSA9IDEpCmNyZl9jX3ZhcmltcF9jb25kX3ByZXYgPC0gdmFyaW1wKGNyZl9jX2ZpdF9wcmV2LCBjb25kaXRpb25hbCA9IFQsIG5wZXJtID0gMSkKCmNyZl9jX3ZhcmltcF9wcmV2ICU+JSBhcy5kYXRhLmZyYW1lKCkgJT4lIHJvd25hbWVzX3RvX2NvbHVtbigndmFyaWFibGUnKSAlPiUKICBnZ3Bsb3QoYWVzKHg9dmFyaWFibGUsIHk9LikpICsKICBnZW9tX2JhcihzdGF0ID0gJ2lkZW50aXR5JykgKyAKICB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDkwKSkKCmNyZl9jX3ZhcmltcF9jb25kX3ByZXYgJT4lIGFzLmRhdGEuZnJhbWUoKSAlPiUgcm93bmFtZXNfdG9fY29sdW1uKCd2YXJpYWJsZScpICU+JQogIGdncGxvdChhZXMoeD12YXJpYWJsZSwgeT0uKSkgKwogIGdlb21fYmFyKHN0YXQgPSAnaWRlbnRpdHknKSArIAogIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gOTApKQoKYGBgCgoKIyBDUkYgcHJldmFsZW5jZSB+IGV4dHJhdmVyc2lvbgpgYGB7cn0KCmN0cmxzIDwtIGNmb3Jlc3RfdW5iaWFzZWQobnRyZWU9NTAwLCBtdHJ5PTUpCgpjcmZfZV9maXRfcHJldiA8LSBjZm9yZXN0KHNsb3BlX3ByZXYgfiBwZXJzX2UgKyBhaXJwb3J0X2Rpc3QgKyBtYWxlcyArCiAgICAgICAgICAgICAgICAgICAgICAgICAgcG9wZGVucyArIG1hbnVmYWN0dXJpbmcgKyB0b3VyaXNtICsKICAgICAgICAgICAgICAgICAgICAgICAgICBoZWFsdGggKyBhY2FkZW1pYyArIG1lZGluYyArIG1lZGFnZSArIGNvbnNlcnZhdGl2ZSwgCiAgICAgICAgICAgICAgICAgICAgICAgICBkZl91a19zbG9wZV9wcmV2Wy0xXSwgCiAgICAgICAgICAgICAgICAgICAgICAgICBjb250cm9scyA9IGN0cmxzKQoKY3JmX2VfdmFyaW1wX3ByZXYgPC0gdmFyaW1wKGNyZl9lX2ZpdF9wcmV2LCBucGVybSA9IDEpCmNyZl9lX3ZhcmltcF9jb25kX3ByZXYgPC0gdmFyaW1wKGNyZl9lX2ZpdF9wcmV2LCBjb25kaXRpb25hbCA9IFQsIG5wZXJtID0gMSkKCmNyZl9lX3ZhcmltcF9wcmV2ICU+JSBhcy5kYXRhLmZyYW1lKCkgJT4lIHJvd25hbWVzX3RvX2NvbHVtbigndmFyaWFibGUnKSAlPiUKICBnZ3Bsb3QoYWVzKHg9dmFyaWFibGUsIHk9LikpICsKICBnZW9tX2JhcihzdGF0ID0gJ2lkZW50aXR5JykgKyAKICB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDkwKSkKCmNyZl9lX3ZhcmltcF9jb25kX3ByZXYgJT4lIGFzLmRhdGEuZnJhbWUoKSAlPiUgcm93bmFtZXNfdG9fY29sdW1uKCd2YXJpYWJsZScpICU+JQogIGdncGxvdChhZXMoeD12YXJpYWJsZSwgeT0uKSkgKwogIGdlb21fYmFyKHN0YXQgPSAnaWRlbnRpdHknKSArIAogIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gOTApKQoKYGBgCgoKIyBDUkYgcHJldmFsZW5jZSB+IGFncmVlYWJsZW5lc3MKYGBge3J9CgpjdHJscyA8LSBjZm9yZXN0X3VuYmlhc2VkKG50cmVlPTUwMCwgbXRyeT01KQoKY3JmX2FfZml0X3ByZXYgPC0gY2ZvcmVzdChzbG9wZV9wcmV2IH4gcGVyc19hICsgYWlycG9ydF9kaXN0ICsgbWFsZXMgKwogICAgICAgICAgICAgICAgICAgICAgICAgIHBvcGRlbnMgKyBtYW51ZmFjdHVyaW5nICsgdG91cmlzbSArCiAgICAgICAgICAgICAgICAgICAgICAgICAgaGVhbHRoICsgYWNhZGVtaWMgKyBtZWRpbmMgKyBtZWRhZ2UgKyBjb25zZXJ2YXRpdmUsIAogICAgICAgICAgICAgICAgICAgICAgICAgZGZfdWtfc2xvcGVfcHJldlstMV0sIAogICAgICAgICAgICAgICAgICAgICAgICAgY29udHJvbHMgPSBjdHJscykKCmNyZl9hX3ZhcmltcF9wcmV2IDwtIHZhcmltcChjcmZfYV9maXRfcHJldiwgbnBlcm0gPSAxKQpjcmZfYV92YXJpbXBfY29uZF9wcmV2IDwtIHZhcmltcChjcmZfYV9maXRfcHJldiwgY29uZGl0aW9uYWwgPSBULCBucGVybSA9IDEpCgpjcmZfYV92YXJpbXBfcHJldiAlPiUgYXMuZGF0YS5mcmFtZSgpICU+JSByb3duYW1lc190b19jb2x1bW4oJ3ZhcmlhYmxlJykgJT4lCiAgZ2dwbG90KGFlcyh4PXZhcmlhYmxlLCB5PS4pKSArCiAgZ2VvbV9iYXIoc3RhdCA9ICdpZGVudGl0eScpICsgCiAgdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSA5MCkpCgpjcmZfYV92YXJpbXBfY29uZF9wcmV2ICU+JSBhcy5kYXRhLmZyYW1lKCkgJT4lIHJvd25hbWVzX3RvX2NvbHVtbigndmFyaWFibGUnKSAlPiUKICBnZ3Bsb3QoYWVzKHg9dmFyaWFibGUsIHk9LikpICsKICBnZW9tX2JhcihzdGF0ID0gJ2lkZW50aXR5JykgKyAKICB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDkwKSkKCmBgYAoKCiMgQ1JGIHByZXZhbGVuY2UgfiBuZXVyb3RpY2lzbQpgYGB7cn0KCmN0cmxzIDwtIGNmb3Jlc3RfdW5iaWFzZWQobnRyZWU9NTAwLCBtdHJ5PTUpCgpjcmZfbl9maXRfcHJldiA8LSBjZm9yZXN0KHNsb3BlX3ByZXYgfiBwZXJzX24gKyBhaXJwb3J0X2Rpc3QgKyBtYWxlcyArCiAgICAgICAgICAgICAgICAgICAgICAgICAgcG9wZGVucyArIG1hbnVmYWN0dXJpbmcgKyB0b3VyaXNtICsKICAgICAgICAgICAgICAgICAgICAgICAgICBoZWFsdGggKyBhY2FkZW1pYyArIG1lZGluYyArIG1lZGFnZSArIGNvbnNlcnZhdGl2ZSwgCiAgICAgICAgICAgICAgICAgICAgICAgICBkZl91a19zbG9wZV9wcmV2Wy0xXSwgCiAgICAgICAgICAgICAgICAgICAgICAgICBjb250cm9scyA9IGN0cmxzKQoKY3JmX25fdmFyaW1wX3ByZXYgPC0gdmFyaW1wKGNyZl9uX2ZpdF9wcmV2LCBucGVybSA9IDEpCmNyZl9uX3ZhcmltcF9jb25kX3ByZXYgPC0gdmFyaW1wKGNyZl9uX2ZpdF9wcmV2LCBjb25kaXRpb25hbCA9IFQsIG5wZXJtID0gMSkKCmNyZl9uX3ZhcmltcF9wcmV2ICU+JSBhcy5kYXRhLmZyYW1lKCkgJT4lIHJvd25hbWVzX3RvX2NvbHVtbigndmFyaWFibGUnKSAlPiUKICBnZ3Bsb3QoYWVzKHg9dmFyaWFibGUsIHk9LikpICsKICBnZW9tX2JhcihzdGF0ID0gJ2lkZW50aXR5JykgKyAKICB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDkwKSkKCmNyZl9uX3ZhcmltcF9jb25kX3ByZXYgJT4lIGFzLmRhdGEuZnJhbWUoKSAlPiUgcm93bmFtZXNfdG9fY29sdW1uKCd2YXJpYWJsZScpICU+JQogIGdncGxvdChhZXMoeD12YXJpYWJsZSwgeT0uKSkgKwogIGdlb21fYmFyKHN0YXQgPSAnaWRlbnRpdHknKSArIAogIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gOTApKQoKYGBgCgoKIyBDUkYgc29jaWFsIGRpc3RhbmNpbmcgfiBvcGVubmVzcwpgYGB7cn0KCmN0cmxzIDwtIGNmb3Jlc3RfdW5iaWFzZWQobnRyZWU9NTAwLCBtdHJ5PTUpCgpjcmZfb19maXRfc29jZGlzdCA8LSBjZm9yZXN0KHNsb3BlX3NvY2Rpc3QgfiBwZXJzX28gKyBhaXJwb3J0X2Rpc3QgKyBtYWxlcyArCiAgICAgICAgICAgICAgICAgICAgICAgICAgcG9wZGVucyArIG1hbnVmYWN0dXJpbmcgKyB0b3VyaXNtICsKICAgICAgICAgICAgICAgICAgICAgICAgICBoZWFsdGggKyBhY2FkZW1pYyArIG1lZGluYyArIG1lZGFnZSArIGNvbnNlcnZhdGl2ZSwgCiAgICAgICAgICAgICAgICAgICAgICAgICBkZl91a19zbG9wZV9zb2NkaXN0Wy0xXSwgCiAgICAgICAgICAgICAgICAgICAgICAgICBjb250cm9scyA9IGN0cmxzKQoKY3JmX29fdmFyaW1wX3NvY2Rpc3QgPC0gdmFyaW1wKGNyZl9vX2ZpdF9zb2NkaXN0LCBucGVybSA9IDEpCmNyZl9vX3ZhcmltcF9jb25kX3NvY2Rpc3QgPC0gdmFyaW1wKGNyZl9vX2ZpdF9zb2NkaXN0LCBjb25kaXRpb25hbCA9IFQsIG5wZXJtID0gMSkKCmNyZl9vX3ZhcmltcF9zb2NkaXN0ICU+JSBhcy5kYXRhLmZyYW1lKCkgJT4lIHJvd25hbWVzX3RvX2NvbHVtbigndmFyaWFibGUnKSAlPiUKICBnZ3Bsb3QoYWVzKHg9dmFyaWFibGUsIHk9LikpICsKICBnZW9tX2JhcihzdGF0ID0gJ2lkZW50aXR5JykgKyAKICB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDkwKSkKCmNyZl9vX3ZhcmltcF9jb25kX3NvY2Rpc3QgJT4lIGFzLmRhdGEuZnJhbWUoKSAlPiUgcm93bmFtZXNfdG9fY29sdW1uKCd2YXJpYWJsZScpICU+JQogIGdncGxvdChhZXMoeD12YXJpYWJsZSwgeT0uKSkgKwogIGdlb21fYmFyKHN0YXQgPSAnaWRlbnRpdHknKSArIAogIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gOTApKQoKYGBgCgojIENSRiBzb2NpYWwgZGlzdGFuY2luZyB+IGNvbnNjaWVudGlvdXNuZXNzCmBgYHtyfQoKY3RybHMgPC0gY2ZvcmVzdF91bmJpYXNlZChudHJlZT01MDAsIG10cnk9NSkKCmNyZl9jX2ZpdF9zb2NkaXN0IDwtIGNmb3Jlc3Qoc2xvcGVfc29jZGlzdCB+IHBlcnNfYyArIGFpcnBvcnRfZGlzdCArIG1hbGVzICsKICAgICAgICAgICAgICAgICAgICAgICAgICBwb3BkZW5zICsgbWFudWZhY3R1cmluZyArIHRvdXJpc20gKwogICAgICAgICAgICAgICAgICAgICAgICAgIGhlYWx0aCArIGFjYWRlbWljICsgbWVkaW5jICsgbWVkYWdlICsgY29uc2VydmF0aXZlLCAKICAgICAgICAgICAgICAgICAgICAgICAgIGRmX3VrX3Nsb3BlX3NvY2Rpc3RbLTFdLCAKICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnRyb2xzID0gY3RybHMpCgpjcmZfY192YXJpbXBfc29jZGlzdCA8LSB2YXJpbXAoY3JmX2NfZml0X3NvY2Rpc3QsIG5wZXJtID0gMSkKY3JmX2NfdmFyaW1wX2NvbmRfc29jZGlzdCA8LSB2YXJpbXAoY3JmX2NfZml0X3NvY2Rpc3QsIGNvbmRpdGlvbmFsID0gVCwgbnBlcm0gPSAxKQoKY3JmX2NfdmFyaW1wX3NvY2Rpc3QgJT4lIGFzLmRhdGEuZnJhbWUoKSAlPiUgcm93bmFtZXNfdG9fY29sdW1uKCd2YXJpYWJsZScpICU+JQogIGdncGxvdChhZXMoeD12YXJpYWJsZSwgeT0uKSkgKwogIGdlb21fYmFyKHN0YXQgPSAnaWRlbnRpdHknKSArIAogIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gOTApKQoKY3JmX2NfdmFyaW1wX2NvbmRfc29jZGlzdCAlPiUgYXMuZGF0YS5mcmFtZSgpICU+JSByb3duYW1lc190b19jb2x1bW4oJ3ZhcmlhYmxlJykgJT4lCiAgZ2dwbG90KGFlcyh4PXZhcmlhYmxlLCB5PS4pKSArCiAgZ2VvbV9iYXIoc3RhdCA9ICdpZGVudGl0eScpICsgCiAgdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSA5MCkpCgpgYGAKCiMgQ1JGIHNvY2lhbCBkaXN0YW5jaW5nIH4gZXh0cmF2ZXJzaW9uCmBgYHtyfQoKY3RybHMgPC0gY2ZvcmVzdF91bmJpYXNlZChudHJlZT01MDAsIG10cnk9NSkKCmNyZl9lX2ZpdF9zb2NkaXN0IDwtIGNmb3Jlc3Qoc2xvcGVfc29jZGlzdCB+IHBlcnNfZSArIGFpcnBvcnRfZGlzdCArIG1hbGVzICsKICAgICAgICAgICAgICAgICAgICAgICAgICBwb3BkZW5zICsgbWFudWZhY3R1cmluZyArIHRvdXJpc20gKwogICAgICAgICAgICAgICAgICAgICAgICAgIGhlYWx0aCArIGFjYWRlbWljICsgbWVkaW5jICsgbWVkYWdlICsgY29uc2VydmF0aXZlLCAKICAgICAgICAgICAgICAgICAgICAgICAgIGRmX3VrX3Nsb3BlX3NvY2Rpc3RbLTFdLCAKICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnRyb2xzID0gY3RybHMpCgpjcmZfZV92YXJpbXBfc29jZGlzdCA8LSB2YXJpbXAoY3JmX2VfZml0X3NvY2Rpc3QsIG5wZXJtID0gMSkKY3JmX2VfdmFyaW1wX2NvbmRfc29jZGlzdCA8LSB2YXJpbXAoY3JmX2VfZml0X3NvY2Rpc3QsIGNvbmRpdGlvbmFsID0gVCwgbnBlcm0gPSAxKQoKY3JmX2VfdmFyaW1wX3NvY2Rpc3QgJT4lIGFzLmRhdGEuZnJhbWUoKSAlPiUgcm93bmFtZXNfdG9fY29sdW1uKCd2YXJpYWJsZScpICU+JQogIGdncGxvdChhZXMoeD12YXJpYWJsZSwgeT0uKSkgKwogIGdlb21fYmFyKHN0YXQgPSAnaWRlbnRpdHknKSArIAogIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gOTApKQoKY3JmX2VfdmFyaW1wX2NvbmRfc29jZGlzdCAlPiUgYXMuZGF0YS5mcmFtZSgpICU+JSByb3duYW1lc190b19jb2x1bW4oJ3ZhcmlhYmxlJykgJT4lCiAgZ2dwbG90KGFlcyh4PXZhcmlhYmxlLCB5PS4pKSArCiAgZ2VvbV9iYXIoc3RhdCA9ICdpZGVudGl0eScpICsgCiAgdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSA5MCkpCgpgYGAKCiMgQ1JGIHNvY2lhbCBkaXN0YW5jaW5nIH4gYWdyZWVhYmxlbmVzcwpgYGB7cn0KCmN0cmxzIDwtIGNmb3Jlc3RfdW5iaWFzZWQobnRyZWU9NTAwLCBtdHJ5PTUpCgpjcmZfYV9maXRfc29jZGlzdCA8LSBjZm9yZXN0KHNsb3BlX3NvY2Rpc3QgfiBwZXJzX2EgKyBhaXJwb3J0X2Rpc3QgKyBtYWxlcyArCiAgICAgICAgICAgICAgICAgICAgICAgICAgcG9wZGVucyArIG1hbnVmYWN0dXJpbmcgKyB0b3VyaXNtICsKICAgICAgICAgICAgICAgICAgICAgICAgICBoZWFsdGggKyBhY2FkZW1pYyArIG1lZGluYyArIG1lZGFnZSArIGNvbnNlcnZhdGl2ZSwgCiAgICAgICAgICAgICAgICAgICAgICAgICBkZl91a19zbG9wZV9zb2NkaXN0Wy0xXSwgCiAgICAgICAgICAgICAgICAgICAgICAgICBjb250cm9scyA9IGN0cmxzKQoKY3JmX2FfdmFyaW1wX3NvY2Rpc3QgPC0gdmFyaW1wKGNyZl9hX2ZpdF9zb2NkaXN0LCBucGVybSA9IDEpCmNyZl9hX3ZhcmltcF9jb25kX3NvY2Rpc3QgPC0gdmFyaW1wKGNyZl9hX2ZpdF9zb2NkaXN0LCBjb25kaXRpb25hbCA9IFQsIG5wZXJtID0gMSkKCmNyZl9hX3ZhcmltcF9zb2NkaXN0ICU+JSBhcy5kYXRhLmZyYW1lKCkgJT4lIHJvd25hbWVzX3RvX2NvbHVtbigndmFyaWFibGUnKSAlPiUKICBnZ3Bsb3QoYWVzKHg9dmFyaWFibGUsIHk9LikpICsKICBnZW9tX2JhcihzdGF0ID0gJ2lkZW50aXR5JykgKyAKICB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDkwKSkKCmNyZl9hX3ZhcmltcF9jb25kX3NvY2Rpc3QgJT4lIGFzLmRhdGEuZnJhbWUoKSAlPiUgcm93bmFtZXNfdG9fY29sdW1uKCd2YXJpYWJsZScpICU+JQogIGdncGxvdChhZXMoeD12YXJpYWJsZSwgeT0uKSkgKwogIGdlb21fYmFyKHN0YXQgPSAnaWRlbnRpdHknKSArIAogIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gOTApKQoKYGBgCgoKIyBDUkYgc29jaWFsIGRpc3RhbmNpbmcgfiBuZXVyb3RpY2lzbQpgYGB7cn0KCmN0cmxzIDwtIGNmb3Jlc3RfdW5iaWFzZWQobnRyZWU9NTAwLCBtdHJ5PTUpCgpjcmZfbl9maXRfc29jZGlzdCA8LSBjZm9yZXN0KHNsb3BlX3NvY2Rpc3QgfiBwZXJzX24gKyBhaXJwb3J0X2Rpc3QgKyBtYWxlcyArCiAgICAgICAgICAgICAgICAgICAgICAgICAgcG9wZGVucyArIG1hbnVmYWN0dXJpbmcgKyB0b3VyaXNtICsKICAgICAgICAgICAgICAgICAgICAgICAgICBoZWFsdGggKyBhY2FkZW1pYyArIG1lZGluYyArIG1lZGFnZSArIGNvbnNlcnZhdGl2ZSwgCiAgICAgICAgICAgICAgICAgICAgICAgICBkZl91a19zbG9wZV9zb2NkaXN0Wy0xXSwgCiAgICAgICAgICAgICAgICAgICAgICAgICBjb250cm9scyA9IGN0cmxzKQoKY3JmX25fdmFyaW1wX3NvY2Rpc3QgPC0gdmFyaW1wKGNyZl9uX2ZpdF9zb2NkaXN0LCBucGVybSA9IDEpCmNyZl9uX3ZhcmltcF9jb25kX3NvY2Rpc3QgPC0gdmFyaW1wKGNyZl9uX2ZpdF9zb2NkaXN0LCBjb25kaXRpb25hbCA9IFQsIG5wZXJtID0gMSkKCmNyZl9uX3ZhcmltcF9zb2NkaXN0ICU+JSBhcy5kYXRhLmZyYW1lKCkgJT4lIHJvd25hbWVzX3RvX2NvbHVtbigndmFyaWFibGUnKSAlPiUKICBnZ3Bsb3QoYWVzKHg9dmFyaWFibGUsIHk9LikpICsKICBnZW9tX2JhcihzdGF0ID0gJ2lkZW50aXR5JykgKyAKICB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDkwKSkKCmNyZl9uX3ZhcmltcF9jb25kX3NvY2Rpc3QgJT4lIGFzLmRhdGEuZnJhbWUoKSAlPiUgcm93bmFtZXNfdG9fY29sdW1uKCd2YXJpYWJsZScpICU+JQogIGdncGxvdChhZXMoeD12YXJpYWJsZSwgeT0uKSkgKwogIGdlb21fYmFyKHN0YXQgPSAnaWRlbnRpdHknKSArIAogIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gOTApKQoKYGBgCgojIENoYW5nZSBwb2ludCBhbmFseXNpcwojIyMgUHJlcGFyYXRpb24KYGBge3J9CgojIGtlZXAgb25seSBjb3VudGllcyB3aXRoIGZ1bGwgZGF0YQp1dF9hcmVhX2NvbXBsZXRlIDwtIGRmX3VrX3NjYWxlZCAlPiUgCiAgZ3JvdXBfYnkodXRfYXJlYSkgJT4lCiAgc3VtbWFyaXplKG4gPSBuKCkpICU+JQogIGZpbHRlcihuPT1tYXgoLiRuKSkgJT4lIAogIC4kdXRfYXJlYQoKIyBrZWVwIG9ubHkgY291bnRpZXMgd2l0aCBmdWxsIGRhdGEKbnV0czNfY29tcGxldGUgPC0gZGZfdWtfc29jZGlzdF9zY2FsZWQgJT4lIAogIGdyb3VwX2J5KG51dHMzKSAlPiUKICBzdW1tYXJpemUobiA9IG4oKSkgJT4lCiAgZmlsdGVyKG49PW1heCguJG4pKSAlPiUgCiAgLiRudXRzMwpgYGAKCiMjIyBQcmV2YWxlbmNlCmBgYHtyfQoKIyBydW4gY2hhbmdlcG9pbnQgYW5hbHlzaXMKZGZfdWtfcHJldl9jcHRfcmVzdWx0cyA8LSBkZl91a19zY2FsZWQgJT4lIHNlbGVjdCh1dF9hcmVhLCByYXRlX2RheSkgJT4lCiAgZmlsdGVyKHV0X2FyZWEgJWluJSB1dF9hcmVhX2NvbXBsZXRlKSAlPiUgCiAgc3BsaXQoLiR1dF9hcmVhKSAlPiUKICBtYXAofiBjcHQubWVhbnZhcihhcy52ZWN0b3IoLiRyYXRlX2RheSksCiAgICAgICAgICAgICAgICAgICAgY2xhc3M9VFJVRSwKICAgICAgICAgICAgICAgICAgICBwYXJhbS5lc3RpbWF0ZXM9VFJVRSwKICAgICAgICAgICAgICAgICAgICBRPTEpKQoKIyBjYWxjdWxhdGUgY2hhbmdlIHBvaW50cwpkZl91a19wcmV2X2NwdF9kYXkgPC0gZGZfdWtfcHJldl9jcHRfcmVzdWx0cyAlPiUgCiAgbWFwKGNwdHMpICU+JSAKICB1bmxpc3QoKSAlPiUgCiAgYXMuZGF0YS5mcmFtZSgpICU+JSAKICByZW5hbWUoY3B0X2RheV9wcmV2ID0gJy4nKSAlPiUKICByb3duYW1lc190b19jb2x1bW4oJ3V0X2FyZWEnKQoKIyBjYWxjdWxhdGUgbWVhbiBkaWZmZXJlbmNlcwpkZl91a19wcmV2X2NwdF9tZWFuX2RpZmYgPC0gZGZfdWtfcHJldl9jcHRfcmVzdWx0cyAlPiUgCiAgbWFwKHBhcmFtLmVzdCkgJT4lIAogIG1hcCh+IC4kbWVhbikgJT4lIAogIG1hcCh+IC5bMl0tLlsxXSkgJT4lIAogIHVubGlzdCgpICU+JSAKICBhcy5kYXRhLmZyYW1lKCkgJT4lIAogIHJlbmFtZShtZWFuX2RpZmZfcHJldiA9ICcuJykgJT4lCiAgcm93bmFtZXNfdG9fY29sdW1uKCd1dF9hcmVhJykKCiMgY2FsY3VsYXRlIHZhcmFpbmNlIGRpZmZlcmVuY2VzCmRmX3VrX3ByZXZfY3B0X3Zhcl9kaWZmIDwtIGRmX3VrX3ByZXZfY3B0X3Jlc3VsdHMgJT4lIAogIG1hcChwYXJhbS5lc3QpICU+JSAKICBtYXAofiAuJHZhcmlhbmNlKSAlPiUgCiAgbWFwKH4gLlsyXS0uWzFdKSAlPiUgCiAgdW5saXN0KCkgJT4lIAogIGFzLmRhdGEuZnJhbWUoKSAlPiUgCiAgcmVuYW1lKHZhcl9kaWZmX3ByZXYgPSAnLicpICU+JQogIHJvd25hbWVzX3RvX2NvbHVtbigndXRfYXJlYScpCgojIG1lcmdlIG5ldyB2YXJpYWJsZXMgCmRmX3VrX2NwdF9wcmV2IDwtIGRmX3VrX3NjYWxlZCAlPiUKICBzZWxlY3QoLXRpbWUsIC1yYXRlX2RheSkgJT4lCiAgZGlzdGluY3QoKSAlPiUKICBtdXRhdGUodXRfYXJlYSA9IGFzLmNoYXJhY3Rlcih1dF9hcmVhKSkgJT4lCiAgbGVmdF9qb2luKGRmX3VrX3ByZXZfY3B0X2RheSwgYnk9J3V0X2FyZWEnKSAlPiUKICBsZWZ0X2pvaW4oZGZfdWtfcHJldl9jcHRfbWVhbl9kaWZmLCBieT0ndXRfYXJlYScpICU+JQogIGxlZnRfam9pbihkZl91a19wcmV2X2NwdF92YXJfZGlmZiwgYnk9J3V0X2FyZWEnKQoKZGZfdWtfY3B0X3ByZXYgJT4lIHNlbGVjdChjcHRfZGF5X3ByZXYpICU+JSBtYXAoaGlzdCkKZGZfdWtfY3B0X3ByZXYgJT4lIHNlbGVjdChtZWFuX2RpZmZfcHJldikgJT4lIG1hcChoaXN0KQpkZl91a19jcHRfcHJldiAlPiUgc2VsZWN0KHZhcl9kaWZmX3ByZXYpICU+JSBtYXAoaGlzdCkKCmRmX3VrX2NwdF9wcmV2ICU+JSBkaW0oKQpkZl91a19jcHRfcHJldiAlPiUgZHJvcF9uYSgpICU+JSBkaW0oKQoKYGBgCgoKYGBge3J9Cgpmb3IoaSBpbiBoZWFkKGRmX3VrX3ByZXZfY3B0X3Jlc3VsdHMsNSkpewogIHBsb3QoaSkKfQoKYGBgCgoKCiMjIyBTb2NpYWwgZGlzdGFuY2luZwpgYGB7cn0KCiMgcnVuIGNoYW5nZXBvaW50IGFuYWx5c2lzCmRmX3VrX3NvY2Rpc3RfY3B0X3Jlc3VsdHMgPC0gZGZfdWtfc29jZGlzdF9zY2FsZWQgJT4lIHNlbGVjdChudXRzMywgc29jZGlzdF9zaW5nbGVfdGlsZSkgJT4lCiAgZmlsdGVyKG51dHMzICVpbiUgbnV0czNfY29tcGxldGUpICU+JSAKICBzcGxpdCguJG51dHMzKSAlPiUKICBtYXAofiBjcHQubWVhbnZhcihhcy52ZWN0b3IoLiRzb2NkaXN0X3NpbmdsZV90aWxlKSwKICAgICAgICAgICAgICAgICAgICAjcGVuYWx0eSA9ICdBc3ltcHRvdGljJywKICAgICAgICAgICAgICAgICAgICBjbGFzcz1UUlVFLAogICAgICAgICAgICAgICAgICAgIHBhcmFtLmVzdGltYXRlcz1UUlVFLAogICAgICAgICAgICAgICAgICAgIFE9MSwKICAgICAgICAgICAgICAgICAgICB0ZXN0LnN0YXQgPSAnTm9ybWFsJykpCgojIGNhbGN1bGF0ZSBjaGFuZ2UgcG9pbnQKZGZfdWtfc29jZGlzdF9jcHRfZGF5IDwtIGRmX3VrX3NvY2Rpc3RfY3B0X3Jlc3VsdHMgJT4lIAogIG1hcChjcHRzKSAlPiUgCiAgdW5saXN0KCkgJT4lIAogIGFzLmRhdGEuZnJhbWUoKSAlPiUgCiAgcmVuYW1lKGNwdF9kYXlfc29jZGlzdCA9ICcuJykgJT4lCiAgcm93bmFtZXNfdG9fY29sdW1uKCdudXRzMycpCgojIGNhbGN1bGF0ZSBtZWFuIGRpZmZlcmVuY2VzCmRmX3VrX3NvY2Rpc3RfY3B0X21lYW5fZGlmZiA8LSBkZl91a19zb2NkaXN0X2NwdF9yZXN1bHRzICU+JSAKICBtYXAocGFyYW0uZXN0KSAlPiUgCiAgbWFwKH4gLiRtZWFuKSAlPiUgCiAgbWFwKH4gLlsyXS0uWzFdKSAlPiUgCiAgdW5saXN0KCkgJT4lIAogIGFzLmRhdGEuZnJhbWUoKSAlPiUgCiAgcmVuYW1lKG1lYW5fZGlmZl9zb2NkaXN0ID0gJy4nKSAlPiUKICByb3duYW1lc190b19jb2x1bW4oJ251dHMzJykKCiMgY2FsY3VsYXRlIHZhcmFpbmNlIGRpZmZlcmVuY2VzCmRmX3VrX3NvY2Rpc3RfY3B0X3Zhcl9kaWZmIDwtIGRmX3VrX3NvY2Rpc3RfY3B0X3Jlc3VsdHMgJT4lIAogIG1hcChwYXJhbS5lc3QpICU+JSAKICBtYXAofiAuJHZhcmlhbmNlKSAlPiUgCiAgbWFwKH4gLlsyXS0uWzFdKSAlPiUgCiAgdW5saXN0KCkgJT4lIAogIGFzLmRhdGEuZnJhbWUoKSAlPiUgCiAgcmVuYW1lKHZhcl9kaWZmX3NvY2Rpc3QgPSAnLicpICU+JQogIHJvd25hbWVzX3RvX2NvbHVtbignbnV0czMnKQoKIyBtZXJnZSBuZXcgdmFyaWFibGVzIApkZl91a19jcHRfcHJldl9zb2NkaXN0IDwtIGRmX3VrX2NwdF9wcmV2ICU+JQogIGxlZnRfam9pbihkZl91a19zb2NkaXN0X2NwdF9kYXksIGJ5PSdudXRzMycpICU+JQogIGxlZnRfam9pbihkZl91a19zb2NkaXN0X2NwdF9tZWFuX2RpZmYsIGJ5PSdudXRzMycpICU+JQogIGxlZnRfam9pbihkZl91a19zb2NkaXN0X2NwdF92YXJfZGlmZiwgYnk9J251dHMzJykKCmRmX3VrX2NwdF9wcmV2X3NvY2Rpc3QgJT4lIHNlbGVjdChjcHRfZGF5X3NvY2Rpc3QpICU+JSBtYXAoaGlzdCkKZGZfdWtfY3B0X3ByZXZfc29jZGlzdCAlPiUgc2VsZWN0KG1lYW5fZGlmZl9zb2NkaXN0KSAlPiUgbWFwKGhpc3QpCmRmX3VrX2NwdF9wcmV2X3NvY2Rpc3QgJT4lIHNlbGVjdCh2YXJfZGlmZl9zb2NkaXN0KSAlPiUgbWFwKGhpc3QpCgpkZl91a19jcHRfcHJldl9zb2NkaXN0ICU+JSBkaW0oKQpkZl91a19jcHRfcHJldl9zb2NkaXN0ICU+JSBkcm9wX25hKCkgJT4lIGRpbSgpCgpgYGAKCmBgYHtyfQoKZm9yKGkgaW4gaGVhZChkZl91a19zb2NkaXN0X2NwdF9yZXN1bHRzLDUpKXsKICBwbG90KGkpCn0KCmBgYAoKIyBQcmVkaWN0aW5nIGNoYW5nZSBwb2ludHMgCiMjIyBMaW5lYXIgbW9kZWxzIHByZWRpY3RpbmcgY2hhbmdlIHBvaW50cyAobm8gY29udHJvbHMpCmBgYHtyfQoKbG1fY3ByX3ByZXZfcGVycyA8LSBsbShjcHRfZGF5X3ByZXYgfiBwZXJzX28gKyBwZXJzX2MgKyBwZXJzX2UgKyBwZXJzX2EgKyBwZXJzX24sIAogICAgICAgICAgICAgICAgICAgICAgICAgZGF0YSA9IGRmX3VrX2NwdF9wcmV2X3NvY2Rpc3QpCmxtX2Nwcl9wcmV2X3BlcnMgJT4lIHN1bW1hcnkoKQoKCmxtX2NwdF9zb2NkaXN0X3BlcnMgPC0gbG0oY3B0X2RheV9zb2NkaXN0IH4gcGVyc19vICsgcGVyc19jICsgcGVyc19lICsgcGVyc19hICsgcGVyc19uLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRhdGEgPSBkZl91a19jcHRfcHJldl9zb2NkaXN0KQpsbV9jcHRfc29jZGlzdF9wZXJzICU+JSBzdW1tYXJ5KCkKCmBgYAoKIyMjIExpbmVhciBtb2RlbHMgcHJlZGljdGluZyBjaGFuZ2UgcG9pbnRzIHdpdGggY29udHJvbHMKYGBge3J9CmRmX3VrX2NwdF9wcmV2X3NvY2Rpc3QKCmxtX2NwdF9wcmV2X3BlcnMgPC0gbG0oY3B0X2RheV9wcmV2IH4gcGVyc19vICsgcGVyc19jICsgcGVyc19lICsgcGVyc19hICsgcGVyc19uICsgCiAgICAgICAgICAgICAgICAgICAgICAgICB3b21lbiArIGFjYWRlbWljcyArIGhvc3BpdGFsX2JlZHMgKyBnZHAgKyBtYW51ZmFjdCArCiAgICAgICAgICAgICAgICAgICAgICAgICAgYWlycG9ydCArIGFnZSArIHBvcGRlbnMsCiAgICAgICAgICAgICAgICAgICAgICAgICBkYXRhID0gZGZfdWtfY3B0X3ByZXZfc29jZGlzdCkKbG1fY3B0X3ByZXZfcGVycyAlPiUgc3VtbWFyeSgpCgpsbV9jcHRfc29jZGlzdF9wZXJzIDwtIGxtKGNwdF9kYXlfc29jZGlzdCB+IHBlcnNfbyArIHBlcnNfYyArIHBlcnNfZSArIHBlcnNfYSArIHBlcnNfbiArIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgd29tZW4gKyBhY2FkZW1pY3MgKyBob3NwaXRhbF9iZWRzICsgZ2RwICsgbWFudWZhY3QgKwogICAgICAgICAgICAgICAgICAgICAgICAgICAgYWlycG9ydCArIGFnZSArIHBvcGRlbnMsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBkYXRhID0gZGZfdWtfY3B0X3ByZXZfc29jZGlzdCkKbG1fY3B0X3NvY2Rpc3RfcGVycyAlPiUgc3VtbWFyeSgpCgpgYGAK